// events.cpp : Defines the entry point for the console application. // #include #include #include #include #include using namespace std; const int max_parallel_downloads = 5; void test1(); void test2(); void test3(); void parallel_download(int file_list[], int file_count); void download_file(void* data); //for syncing output to screen CRITICAL_SECTION g_cs; int main(int argc, char* argv[]) { InitializeCriticalSection(&g_cs); //test1(); test2(); //test3(); return 0; } //test condition 1 void test1() { int list[5] = {103556, 25560, 356650, 44600, 1000}; parallel_download(list, 5); } //test condition 2 void test2() { int list[10] = {10450, 56200, 35400, 4500, 67004, 7000, 2343, 23494, 4328, 100}; parallel_download(list, 10); } //test condition 3 void test3() { int list[3] = {10450, 56200, 35400}; parallel_download(list, 3); } //data structure to hold file data struct file_data { HANDLE event_handle; char file_number[30]; int file_size; bool finished; file_data(int file_no_in, int file_size_in):file_size(file_size_in), finished(false) { sprintf(file_number, "FILE_%d", file_no_in); event_handle = CreateEvent(NULL, false, false, file_number); //create a new event in non-signalled state } }; //schedule downloads void parallel_download(int file_list[], int file_count) { HANDLE event_handle_list[max_parallel_downloads]; vector file_data_list; DWORD dret; //create a list of files to be downloaded for(int i = 0; i < file_count; i++) { file_data_list.push_back(file_data(i, file_list[i])); } int download_started_count; bool less_than_max_files = max_parallel_downloads > file_count; int max_start_count = less_than_max_files ? file_count : max_parallel_downloads; //in case file count < max parallel downloads //first, start download of max permissible no. of files for(download_started_count = 0; download_started_count < max_start_count; download_started_count++) { event_handle_list[download_started_count] = file_data_list[download_started_count].event_handle; _beginthread(download_file, 0, (void*)(&file_data_list[download_started_count])); } //wait for any one file to finish if not less than max no. of files permissible dret = WaitForMultipleObjects(max_start_count, event_handle_list, less_than_max_files, 300000); if(!less_than_max_files) { bool last_wait; //one of the files has finished downloading, so start another one while(download_started_count + 1 < file_count) { download_started_count++; event_handle_list[dret - WAIT_OBJECT_0] = file_data_list[download_started_count].event_handle; _beginthread(download_file, 0, (void*)(&file_data_list[download_started_count])); last_wait = (download_started_count + 1) == file_count; //if last wait, wait for all to finish, else wait for any one to finish dret = WaitForMultipleObjects(max_start_count, event_handle_list, last_wait, 300000); } } cout<<"\n all files finished\n"; } //thread to download one file void download_file(void* data) { file_data* fdata = (file_data*)data; int download_rate = 10; //kbps EnterCriticalSection(&g_cs); //just for printing cout<<"\n starting file download for file "<file_number<<" of size "<file_size; LeaveCriticalSection(&g_cs); //simulate download at constant download speed for(int i = fdata->file_size; i > 0; i = i - (download_rate*1000/10)) { Sleep(100); } EnterCriticalSection(&g_cs); cout<<"\n download finished for file "<file_number; LeaveCriticalSection(&g_cs); //signal the event SetEvent(fdata->event_handle); } //thread to download: choose a random file size and wait, after finish, signal the event