Compare commits

..

No commits in common. "36468aa958d41f6aed65945c76f6f99914382de9" and "985d2d8d77db240e42e628b51830401a866df322" have entirely different histories.

13 changed files with 470 additions and 385 deletions

2
.gitignore vendored
View File

@ -34,4 +34,4 @@
# Extras # Extras
build build
test/web_server test/page/web_server

View File

@ -3,6 +3,8 @@ add_executable(web_server
) )
add_executable(proxy add_executable(proxy
./proxy.cpp ./multi_threads.cpp
) )
target_include_directories(web_server PUBLIC ${CMAKE_CURRENT_LIST_DIR})

View File

@ -1,382 +1,306 @@
//====================================================== file = weblite.c ===== //====================================================== file = weblite.c =====
//= A super light weight HTTP server = //= A super light weight HTTP server =
//============================================================================= //=============================================================================
//= Notes: = //= Notes: =
//= 1) Compiles for Winsock only since uses Windows threads. Generates = //= 1) Compiles for Winsock only since uses Windows threads. Generates =
//= one warning about unreachable code in main. Ignore this warning. = //= one warning about unreachable code in main. Ignore this warning. =
//= 2) Serves HTML and GIF only. = //= 2) Serves HTML and GIF only. =
//= 3) Sometimes the browser drops a connection when doing a refresh. = //= 3) Sometimes the browser drops a connection when doing a refresh. =
//= This is handled by checking the recv() return code in the function = //= This is handled by checking the recv() return code in the function =
//= that handles GETs. = //= that handles GETs. =
//= 4) The 404 HTML message does not always display in Explorer. = //= 4) The 404 HTML message does not always display in Explorer. =
//=---------------------------------------------------------------------------= //=---------------------------------------------------------------------------=
//= Execution notes: = //= Execution notes: =
//= 1) Execute this program in the directory which will be the root for = //= 1) Execute this program in the directory which will be the root for =
//= all file references (i.e., the directory that is considered at = //= all file references (i.e., the directory that is considered at =
//= "public.html"). = //= "public.html"). =
//= 2) Open a Web browser and surf to http://xxx.xxx.xxx.xxx/yyy where = //= 2) Open a Web browser and surf to http://xxx.xxx.xxx.xxx/yyy where =
//= xxx.xxx.xxx.xxx is the IP address or hostname of the machine that = //= xxx.xxx.xxx.xxx is the IP address or hostname of the machine that =
//= weblite is executing on and yyy is the requested object. = //= weblite is executing on and yyy is the requested object. =
//= 3) The only output (to stdout) from weblite is a message with the = //= 3) The only output (to stdout) from weblite is a message with the =
//= of the file currently being sent = //= of the file currently being sent =
//=---------------------------------------------------------------------------= //=---------------------------------------------------------------------------=
//= Build: bcc32 weblite.c, cl weblite.c wsock32.lib (or ws2_32.lib) = //= Build: bcc32 weblite.c, cl weblite.c wsock32.lib (or ws2_32.lib) =
//= gcc weblite.c -lsocket -lnsl for BSD = //= gcc weblite.c -lsocket -lnsl for BSD =
//=---------------------------------------------------------------------------= //=---------------------------------------------------------------------------=
//= Execute: weblite = //= Execute: weblite =
//=---------------------------------------------------------------------------= //=---------------------------------------------------------------------------=
//= History: KJC (12/29/00) - Genesis (from server.c) = //= History: KJC (12/29/00) - Genesis (from server.c) =
//= HF (01/25/01) - Ported to multi-platform environment = //= HF (01/25/01) - Ported to multi-platform environment =
//============================================================================= //=============================================================================
#define UNIX // WIN for Windows environment, UNIX for BSD or LINUX env. #define UNIX // WIN for Windows environment, UNIX for BSD or LINUX env.
//----- Include files --------------------------------------------------------- //----- Include files ---------------------------------------------------------
#include <stdio.h> // Needed for printf() #include <stdio.h> // Needed for printf()
#include <stdlib.h> // Needed for exit() #include <stdlib.h> // Needed for exit()
#include <string.h> // Needed for strcpy() and strlen() #include <string.h> // Needed for strcpy() and strlen()
#include <fcntl.h> // Needed for file i/o constants #include <fcntl.h> // Needed for file i/o constants
#include <sys/stat.h> // Needed for file i/o constants #include <sys/stat.h> // Needed for file i/o constants
#include <future>
/* FOR BSD UNIX/LINUX ---------------------------------------------------- */
/* FOR BSD UNIX/LINUX ---------------------------------------------------- */ #ifdef UNIX
#ifdef UNIX #include <sys/types.h> //
#include <sys/types.h> // #include <netinet/in.h> //
#include <netinet/in.h> // #include <sys/socket.h> //
#include <sys/socket.h> // #include <arpa/inet.h> //
#include <arpa/inet.h> // #include <unistd.h>
#include <unistd.h> #endif
#endif /* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
/* FOR WIN ---------------------------------------------------------------- */
/* FOR WIN ---------------------------------------------------------------- */ #ifdef WIN
#ifdef WIN #include <stddef.h> // Needed for _threadid
#include <stddef.h> // Needed for _threadid #include <process.h> // Needed for _beginthread() and _endthread()
#include <process.h> // Needed for _beginthread() and _endthread() #include <io.h> // Needed for open(), close(), and eof()
#include <io.h> // Needed for open(), close(), and eof() #include <windows.h> // Needed for all Winsock stuff
#include <winsock2.h> #endif
#include <windows.h> // Needed for all Winsock stuff /* ------------------------------------------------------------------------ */
// Lazy struct fixes
typedef int32_t socklen_t; //----- HTTP response messages ----------------------------------------------
#endif #define OK_IMAGE "HTTP/1.0 200 OK\nContent-Type:image/gif\n\n"
/* ------------------------------------------------------------------------ */ #define OK_TEXT "HTTP/1.0 200 OK\nContent-Type:text/html\n\n"
#define NOTOK_404 "HTTP/1.0 404 Not Found\nContent-Type:text/html\n\n"
#define MESS_404 "<html><body><h1>FILE NOT FOUND</h1></body></html>"
//----- HTTP response messages ----------------------------------------------
#define OK_IMAGE "HTTP/1.0 200 OK\nContent-Type:image/gif\n\n" //----- Defines -------------------------------------------------------------
#define OK_TEXT "HTTP/1.0 200 OK\nContent-Type:text/html\n\n" #define BUF_SIZE 4096 // Buffer size (big enough for a GET)
#define NOTOK_404 "HTTP/1.0 404 Not Found\nContent-Type:text/html\n\n" #define PORT_NUM 7080 // Port number for a Web server
#define MESS_404 "<html><body><h1>FILE NOT FOUND</h1></body></html>"
//----- Function prototypes -------------------------------------------------
//----- Defines ------------------------------------------------------------- /* FOR WIN --------------------------------------------------------------- */
#define BUF_SIZE 4096 // Buffer size (big enough for a GET) #ifdef WIN
#define PORT_NUM 7080 // Port number for a Web server void handle_get(void *in_arg); // Thread function to handle GET
#endif
//----- Function prototypes ------------------------------------------------- /* ----------------------------------------------------------------------- */
void ClientRequest(int server_s, int client_s);
/* FOR WIN --------------------------------------------------------------- */ /* FOR UNIX/LINUX -------------------------------------------------------- */
#ifdef WIN #ifdef UNIX
void handle_get(void *in_arg); // Thread function to handle GET void child_proc(int server_s, int client_s); // Fork function for GET
#endif #endif
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
/* FOR UNIX/LINUX -------------------------------------------------------- */ //===== modeule main ========================================================
#ifdef UNIX int main(void)
void child_proc(int server_s, int client_s); // Fork function for GET {
#endif /* FOR WIN ------------------------------------------------------------- */
/* ----------------------------------------------------------------------- */ #ifdef WIN
WORD wVersionRequested = MAKEWORD(1, 1); // Stuff for WSA functions
//===== modeule main ======================================================== WSADATA wsaData; // Stuff for WSA functions
int main(void) #endif
{ /* --------------------------------------------------------------------- */
/* FOR WIN ------------------------------------------------------------- */
#ifdef WIN unsigned int server_s; // Server socket descriptor
WORD wVersionRequested = MAKEWORD(1, 1); // Stuff for WSA functions struct sockaddr_in server_addr; // Server Internet address
WSADATA wsaData; // Stuff for WSA functions unsigned int client_s; // Client socket descriptor
#endif struct sockaddr_in client_addr; // Client Internet address
/* --------------------------------------------------------------------- */ struct in_addr client_ip_addr; // Client IP address
socklen_t addr_len; // Internet address length
unsigned int server_s; // Server socket descriptor
struct sockaddr_in server_addr; // Server Internet address /* FOR UNIX/LINUX ------------------------------------------------------ */
unsigned int client_s; // Client socket descriptor #ifdef UNIX
struct sockaddr_in client_addr; // Client Internet address int nChild_proc_id; // New child process ID.
struct in_addr client_ip_addr; // Client IP address #endif
socklen_t addr_len; // Internet address length /* --------------------------------------------------------------------- */
/* FOR UNIX/LINUX ------------------------------------------------------ */ /* FOR WIN ------------------------------------------------------------- */
#ifdef UNIX #ifdef WIN
int nChild_proc_id; // New child process ID. // Initialize winsock
#endif WSAStartup(wVersionRequested, &wsaData);
/* --------------------------------------------------------------------- */ #endif
/* --------------------------------------------------------------------- */
/* FOR WIN ------------------------------------------------------------- */
#ifdef WIN // Create a socket, fill-in address information, and then bind it
// Initialize winsock server_s = socket(AF_INET, SOCK_STREAM, 0);
WSAStartup(wVersionRequested, &wsaData); server_addr.sin_family = AF_INET;
#endif server_addr.sin_port = htons(PORT_NUM);
/* --------------------------------------------------------------------- */ server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
bind(server_s, (struct sockaddr *)&server_addr, sizeof(server_addr));
// Create a socket, fill-in address information, and then bind it
server_s = socket(AF_INET, SOCK_STREAM, 0); // Main loop to listen, accept, and then spin-off a thread to handle the GET
if (server_s == -1) while (1)
{ {
printf("ERROR - Unable to create socket on server\n"); // Listen for connections and then accept
exit(1); listen(server_s, 100);
} addr_len = sizeof(client_addr);
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORT_NUM); client_s = accept(server_s, (struct sockaddr *)&client_addr, &addr_len);
server_addr.sin_addr.s_addr = htonl(INADDR_ANY); if (client_s == 0)
int bindRet = bind(server_s, (struct sockaddr *)&server_addr, sizeof(server_addr)); {
if (bindRet == -1) printf("ERROR - Unable to create socket \n");
{ exit(1);
printf("ERROR - Unable to bind socket\n"); }
exit(1);
} /* FOR UNIX/LINUX ---------------------------------------------------- */
// Listen for connections and then accept #ifdef UNIX
listen(server_s, 100); // Spin-off a child process by fork
nChild_proc_id = fork();
// Main loop to listen, accept, and then spin-off a thread to handle the GET
while (1) // Separate the parent and child process here ...
{ if (nChild_proc_id == -1) // if I am a new child, go to the child module.
addr_len = sizeof(client_addr); {
child_proc(server_s, client_s);
client_s = accept(server_s, (struct sockaddr *)&client_addr, &addr_len); }
if (client_s == -1) #endif
{ /* ------------------------------------------------------------------- */
perror("ERROR - Unable to create socket to client\n");
continue; /* FOR WIN ----------------------------------------------------------- */
} #ifdef WIN
// Spin-off a thread to handle this request (pass only client_s)
std::async(std::launch::async, ClientRequest, server_s, client_s); if (_beginthread(handle_get, 4096, (void *)client_s) < 0)
{
/* FOR UNIX/LINUX ---------------------------------------------------- */ printf("ERROR - Unable to create thread \n");
#ifdef UNIX exit(1);
/* }
// Spin-off a child process by fork #endif
nChild_proc_id = fork(); /* ------------------------------------------------------------------- */
}
// Separate the parent and child process here ...
if (nChild_proc_id == -1) // if I am a new child, go to the child module. /* FOR UNIX/LINUX ------------------------------------------------------ */
{ #ifdef UNIX
child_proc(server_s, client_s); // Close the server socket
} close(server_s);
*/ #endif
#endif /* --------------------------------------------------------------------- */
/* ------------------------------------------------------------------- */
/* FOR WIN ------------------------------------------------------------- */
/* FOR WIN ----------------------------------------------------------- */ #ifdef WIN
#ifdef WIN // Close the server socket and clean-up winsock
/* printf("this web server is shutting down .....\a\n");
// Spin-off a thread to handle this request (pass only client_s)
if (_beginthread(handle_get, 4096, (void *)client_s) < 0) closesocket(server_s);
{ WSACleanup();
printf("ERROR - Unable to create thread \n"); #endif
exit(1); /* --------------------------------------------------------------------- */
}
*/ // To make sure this "main" returns an integer.
#endif return (1);
/* ------------------------------------------------------------------- */ }
}
close(server_s); /* FOR WIN --------------------------------------------------------------- */
/* FOR UNIX/LINUX ------------------------------------------------------ */ #ifdef WIN
#ifdef UNIX //===========================================================================
// Close the server socket //= This is is the thread function to handle the GET =
//close(server_s); //= - It is assumed that the request is a GET =
#endif //===========================================================================
/* --------------------------------------------------------------------- */ void handle_get(void *in_arg)
{
/* FOR WIN ------------------------------------------------------------- */ unsigned int client_s; // Client socket descriptor
#ifdef WIN char in_buf[BUF_SIZE]; // Input buffer for GET resquest
// Close the server socket and clean-up winsock char out_buf[BUF_SIZE]; // Output buffer for HTML response
printf("this web server is shutting down .....\a\n"); char *file_name; // File name
unsigned int fh; // File handle
closesocket(server_s); unsigned int buf_len; // Buffer length for file reads
WSACleanup(); unsigned int retcode; // Return code
#endif
/* --------------------------------------------------------------------- */ // Set client_s to in_arg
client_s = (unsigned int)in_arg;
// To make sure this "main" returns an integer.
return (1); // Receive the GET request from the Web browser
} retcode = recv(client_s, in_buf, BUF_SIZE, 0);
void ClientRequest(int server_s, int client_s) { // Handle the GET if there is one (see note #3 in the header)
char in_buf[BUF_SIZE]; // Input buffer for GET resquest if (retcode != -1)
char out_buf[BUF_SIZE]; // Output buffer for HTML response {
char *file_name; // File name // Parse out the filename from the GET request
unsigned int fh; // File handle strtok(in_buf, " ");
unsigned int buf_len; // Buffer length for file reads file_name = strtok(NULL, " ");
unsigned int retcode; // Return code
// Open the requested file
// Receive the GET request from the Web browser // - Start at 2nd char to get rid of leading "\"
retcode = recv(client_s, in_buf, BUF_SIZE, 0); fh = open(&file_name[1], O_RDONLY | O_BINARY, S_IREAD | S_IWRITE);
// Handle the GET if there is one (see note #3 in the header) // Generate and send the response (404 if could not open the file)
if (retcode != -1) if (fh == -1)
{ {
// Parse out the filename from the GET request printf("File %s not found - sending an HTTP 404 \n", &file_name[1]);
strtok(in_buf, " "); strcpy(out_buf, NOTOK_404);
file_name = strtok(NULL, " "); send(client_s, out_buf, strlen(out_buf), 0);
strcpy(out_buf, MESS_404);
// Open the requested file send(client_s, out_buf, strlen(out_buf), 0);
// - Start at 2nd char to get rid of leading "\" }
#ifdef WIN else
fh = open(&file_name[1], O_RDONLY | O_BINARY, S_IREAD | S_IWRITE); {
#endif printf("File %s is being sent \n", &file_name[1]);
#ifdef UNIX if (strstr(file_name, ".gif") != NULL)
fh = open(&file_name[1], O_RDONLY, S_IREAD | S_IWRITE); strcpy(out_buf, OK_IMAGE);
#endif else
strcpy(out_buf, OK_TEXT);
// Generate and send the response (404 if could not open the file) send(client_s, out_buf, strlen(out_buf), 0);
if (fh == -1) while (!eof(fh))
{ {
printf("File %s not found - sending an HTTP 404 \n", &file_name[1]); buf_len = read(fh, out_buf, BUF_SIZE);
strcpy(out_buf, NOTOK_404); send(client_s, out_buf, buf_len, 0);
send(client_s, out_buf, strlen(out_buf), 0); }
strcpy(out_buf, MESS_404); close(fh);
send(client_s, out_buf, strlen(out_buf), 0); }
} }
else
{ // Close the client socket and end the thread
printf("File %s is being sent \n", &file_name[1]); closesocket(client_s);
if (strstr(file_name, ".gif") != NULL) _endthread();
strcpy(out_buf, OK_IMAGE); }
else #endif
strcpy(out_buf, OK_TEXT); /* ----------------------------------------------------------------------- */
send(client_s, out_buf, strlen(out_buf), 0);
do { /* FOR UNIX/LINUX -------------------------------------------------------- */
buf_len = read(fh, out_buf, BUF_SIZE); #ifdef UNIX
send(client_s, out_buf, buf_len, 0); void child_proc(int server_s, int client_s)
} while (buf_len != 0); {
close(fh); char in_buf[BUF_SIZE]; // Input buffer for GET resquest
} char out_buf[BUF_SIZE]; // Output buffer for HTML response
} char *file_name; // File name
// Close the client socket and end the thread unsigned int fh; // File handle
close(client_s); unsigned int buf_len; // Buffer length for file reads
} ssize_t retcode; // Return code
/* FOR WIN --------------------------------------------------------------- */ // Shut down the parent pipe
#ifdef WIN close(server_s);
//===========================================================================
//= This is is the thread function to handle the GET = // Receive the GET request from the Web browser
//= - It is assumed that the request is a GET = retcode = recv(client_s, in_buf, BUF_SIZE, 0);
//===========================================================================
void handle_get(void *in_arg) // Handle the GET if there is one (see note #3 in the header)
{ if (retcode != -1)
unsigned int client_s; // Client socket descriptor {
char in_buf[BUF_SIZE]; // Input buffer for GET resquest // Parse out the filename from the GET request
char out_buf[BUF_SIZE]; // Output buffer for HTML response strtok(in_buf, " ");
char *file_name; // File name file_name = strtok(NULL, " ");
unsigned int fh; // File handle
unsigned int buf_len; // Buffer length for file reads // Open the requested file
unsigned int retcode; // Return code // - Start at 2nd char to get rid of leading "\"
// fh = open(&file_name[1], O_RDONLY | O_BINARY, S_IREAD | S_IWRITE);
// Set client_s to in_arg fh = open(&file_name[1], O_RDONLY, S_IREAD | S_IWRITE);
client_s = (unsigned int&)in_arg;
// Generate and send the response (404 if could not open the file)
// Receive the GET request from the Web browser if (fh == -1)
retcode = recv(client_s, in_buf, BUF_SIZE, 0); {
printf("File %s not found - sending an HTTP 404 \n", &file_name[1]);
// Handle the GET if there is one (see note #3 in the header) strcpy(out_buf, NOTOK_404);
if (retcode != -1) send(client_s, out_buf, strlen(out_buf), 0);
{ strcpy(out_buf, MESS_404);
// Parse out the filename from the GET request send(client_s, out_buf, strlen(out_buf), 0);
strtok(in_buf, " "); }
file_name = strtok(NULL, " "); else
{
// Open the requested file printf("File %s is being sent \n", &file_name[1]);
// - Start at 2nd char to get rid of leading "\" if (strstr(file_name, ".gif") != NULL)
fh = open(&file_name[1], O_RDONLY | O_BINARY, S_IREAD | S_IWRITE); strcpy(out_buf, OK_IMAGE);
else
// Generate and send the response (404 if could not open the file) strcpy(out_buf, OK_TEXT);
if (fh == -1) send(client_s, out_buf, strlen(out_buf), 0);
{
printf("File %s not found - sending an HTTP 404 \n", &file_name[1]); while (fh != EOF)
strcpy(out_buf, NOTOK_404); {
send(client_s, out_buf, strlen(out_buf), 0); buf_len = read(fh, out_buf, BUF_SIZE);
strcpy(out_buf, MESS_404); send(client_s, out_buf, buf_len, 0);
send(client_s, out_buf, strlen(out_buf), 0); }
} close(fh);
else }
{ }
printf("File %s is being sent \n", &file_name[1]);
if (strstr(file_name, ".gif") != NULL) // Shut down my (the child) pipe
strcpy(out_buf, OK_IMAGE); close(client_s);
else exit(1);
strcpy(out_buf, OK_TEXT); }
send(client_s, out_buf, strlen(out_buf), 0); #endif
while (!eof(fh)) /* ----------------------------------------------------------------------- */
{
buf_len = read(fh, out_buf, BUF_SIZE);
send(client_s, out_buf, buf_len, 0);
}
close(fh);
}
}
// Close the client socket and end the thread
closesocket(client_s);
_endthread();
}
#endif
/* ----------------------------------------------------------------------- */
/* FOR UNIX/LINUX -------------------------------------------------------- */
#ifdef UNIX
void child_proc(int server_s, int client_s)
{
char in_buf[BUF_SIZE]; // Input buffer for GET resquest
char out_buf[BUF_SIZE]; // Output buffer for HTML response
char *file_name; // File name
unsigned int fh; // File handle
unsigned int buf_len; // Buffer length for file reads
ssize_t retcode; // Return code
// Shut down the parent pipe
close(server_s);
// Receive the GET request from the Web browser
retcode = recv(client_s, in_buf, BUF_SIZE, 0);
// Handle the GET if there is one (see note #3 in the header)
if (retcode != -1)
{
// Parse out the filename from the GET request
strtok(in_buf, " ");
file_name = strtok(NULL, " ");
// Open the requested file
// - Start at 2nd char to get rid of leading "\"
// fh = open(&file_name[1], O_RDONLY | O_BINARY, S_IREAD | S_IWRITE);
fh = open(&file_name[1], O_RDONLY, S_IREAD | S_IWRITE);
// Generate and send the response (404 if could not open the file)
if (fh == -1)
{
printf("File %s not found - sending an HTTP 404 \n", &file_name[1]);
strcpy(out_buf, NOTOK_404);
send(client_s, out_buf, strlen(out_buf), 0);
strcpy(out_buf, MESS_404);
send(client_s, out_buf, strlen(out_buf), 0);
}
else
{
printf("File %s is being sent \n", &file_name[1]);
if (strstr(file_name, ".gif") != NULL)
strcpy(out_buf, OK_IMAGE);
else
strcpy(out_buf, OK_TEXT);
send(client_s, out_buf, strlen(out_buf), 0);
do {
buf_len = read(fh, out_buf, BUF_SIZE);
send(client_s, out_buf, buf_len, 0);
} while (buf_len != 0);
close(fh);
}
}
// Shut down my (the child) pipe
close(client_s);
exit(1);
}
#endif
/* ----------------------------------------------------------------------- */

124
src/multi_threads.cpp Normal file
View File

@ -0,0 +1,124 @@
/* ************************************************************************* *
* *
* Multi.cpp: *
* This is a sample program for multi-threaded applications. *
* *
* As soon as this program starts, the main thread generates two child *
* threads. The two child threads wait for 10 seconds and terminate. *
* *
* While the two child threads are running, the main thread waits. The *
* main thread waits until both threads finish. *
* *
* Compile: *
* In Project->Setting->C/C++->CodeGenartion(in Category) *
* ->Select Multi-threaded for runtime library *
* *
* Coded by: H. Fujinoki *
* September 12, 11:00 AM at Edwardsville, IL *
* *
* ************************************************************************* */
#include <ratio>
#define UNIX // WIN for Windows environment, UNIX for BSD or LINUX env.
/* FOR WIN ------------------------------------------------------------- */
#ifdef WIN
#include <process.h> // for thread system calls (_beginthread, etc.)
#include <windows.h> // for TRUE, FALSE labels
#endif
/* --------------------------------------------------------------------- */
/* FOR UNIX/LINUX ------------------------------------------------------ */
#ifdef UNIX
#endif
/* --------------------------------------------------------------------- */
#include <chrono>
#include <thread>
#include <stdio.h> // for printf
#include <time.h> // for clock() and CLK_TCK
/* Global label defenition ------------------------------------------------ */
#define INTERVAL 1 // Transmission interval in seconds
#define REPEATS 10 // Number of child thread's repeats
/* Global Variables ------------------------------------------------------- */
int nChild1_status; // Child thread #1 status
int nChild2_status; // Child thread #2 status
/* Prototypes ------------------------------------------------------------- */
void ChildThread1(void); // The child thread #1
void ChildThread2(void); // The child thread #2
/* The MAIN --------------------------------------------------------------- */
int main (void)
{
/* Set the child thread status (TRUE = RUNNING) --- */
nChild1_status = true;
nChild2_status = true;
/* Create and start the two threads --- */
std::thread nChild1(ChildThread1); // Start child process #1
std::thread nChild2(ChildThread2); // Start child process #2
nChild1.join();
nChild2.join();
/* Spin-loop until both threads finish --- */
while ((nChild1_status == true)||(nChild2_status == true))
{ ; }
/* Two threads are now finished --- */
printf("Both child threads are finished ... \n");
printf("The main thread is finishing ... \n");
}
// The Child-Thread #1 ///////////////////////////////////////////////////////
void ChildThread1(void)
{
/* Child #1 local variable(s) --- */
int i; // Loop counter
/* This thread is started --- */
printf("Child Thread #1 has started ... \n");
/* wait for 10 seconds w/ count down --- */
for (i = 0; i < REPEATS; i++)
{
/* Wait for 10 seconds --- */
std::this_thread::sleep_for(std::chrono::duration<double, std::milli>(1000));
/* Display count down --- */
printf("Child #1: %d more second(s) to finish ...\n", REPEATS -i);
}
/* Reset the status flag --- */
nChild1_status = false;
/* Terminate this thread --- */
//_endthread();
}
// The Child-Thread #2 ///////////////////////////////////////////////////////
void ChildThread2(void)
{
/* Child #2 local variable(s) --- */
int i; // Loop counter
/* This thread is started --- */
printf("Child Thread #2 has started ... \n");
/* wait for 10 seconds w/ count down --- */
for (i = 0; i < REPEATS; i++)
{
/* Wait for 10 seconds --- */
std::this_thread::sleep_for(std::chrono::duration<double, std::milli>(1000));
/* Display count down --- */
printf("Child #2: %d more second(s) to finish ...\n", REPEATS -i);
}
/* Reset the status flag --- */
nChild2_status = false;
/* Terminate this thread --- */
//_endthread();
}
// THE END OF LINES //////////////////////////////////////////////////////////

View File

@ -28,7 +28,7 @@
//= History: KJC (12/29/00) - Genesis (from server.c) = //= History: KJC (12/29/00) - Genesis (from server.c) =
//= HF (01/25/01) - Ported to multi-platform environment = //= HF (01/25/01) - Ported to multi-platform environment =
//============================================================================= //=============================================================================
#define UNIX // WIN for Windows environment, UNIX for BSD or LINUX env. #define WIN // WIN for Windows environment, UNIX for BSD or LINUX env.
//----- Include files --------------------------------------------------------- //----- Include files ---------------------------------------------------------
#include <stdio.h> // Needed for printf() #include <stdio.h> // Needed for printf()

7
test/CMakeLists.txt Normal file
View File

@ -0,0 +1,7 @@
find_package(unity REQUIRED)
include_directories(${CMAKE_SOURCE_DIR}/src)
add_executable(testing
./test.cpp
)
set_target_properties(testing PROPERTIES LINKER_LANGUAGE CXX)
target_link_libraries(testing unity)

View File

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 23 KiB

View File

Before

Width:  |  Height:  |  Size: 188 KiB

After

Width:  |  Height:  |  Size: 188 KiB

View File

Before

Width:  |  Height:  |  Size: 83 KiB

After

Width:  |  Height:  |  Size: 83 KiB

View File

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 38 KiB

28
test/test.cpp Normal file
View File

@ -0,0 +1,28 @@
#include <cassert>
#include <iostream>
int math();
void test_math();
void IsEqual(bool lhs, bool rhs);
int main() {
test_math();
return 0;
}
int math() {
return 2+2;
}
void test_math() {
IsEqual(math(), 4);
IsEqual(math(), 6);
}
void IsEqual(bool lhs, bool rhs) {
if (lhs == rhs) {
std::cout << "Test Success" << std::endl;
} else {
std::cout << "Test Failure" << std::endl;
}
}