static void test_setcolors(void) { HWND progress; COLORREF clr; progress = create_progress(PBS_SMOOTH); clr = SendMessageA(progress, PBM_SETBARCOLOR, 0, 0); ok(clr == CLR_DEFAULT, "got %x\n", clr); clr = SendMessageA(progress, PBM_SETBARCOLOR, 0, RGB(0, 255, 0)); ok(clr == 0, "got %x\n", clr); clr = SendMessageA(progress, PBM_SETBARCOLOR, 0, CLR_DEFAULT); ok(clr == RGB(0, 255, 0), "got %x\n", clr); clr = SendMessageA(progress, PBM_SETBKCOLOR, 0, 0); ok(clr == CLR_DEFAULT, "got %x\n", clr); clr = SendMessageA(progress, PBM_SETBKCOLOR, 0, RGB(255, 0, 0)); ok(clr == 0, "got %x\n", clr); clr = SendMessageA(progress, PBM_SETBKCOLOR, 0, CLR_DEFAULT); ok(clr == RGB(255, 0, 0), "got %x\n", clr); DestroyWindow(progress); }
void StreamSorter<Message>::streaming_merge(list<cursor_t>& cursors, emitter_t& emitter, size_t expected_messages) { create_progress("merge " + to_string(cursors.size()) + " files", expected_messages == 0 ? 1 : expected_messages); // Count the messages we actually see size_t observed_messages = 0; // Put all the files in a priority queue based on which has a message that comes first. // We work with pointers to cursors because we don't want to be copying the actual cursors around the heap. // We also *reverse* the order, because priority queues put the "greatest" element first auto cursor_order = [&](cursor_t*& a, cursor_t*& b) { if (b->has_next()) { if(!a->has_next()) { // Cursors that aren't empty come first return true; } return less_than(*(*b), *(*a)); } return false; }; priority_queue<cursor_t*, vector<cursor_t*>, decltype(cursor_order)> cursor_queue(cursor_order); for (auto& cursor : cursors) { // Put the cursor pointers in the queue cursor_queue.push(&cursor); } while(!cursor_queue.empty() && cursor_queue.top()->has_next()) { // Until we have run out of data in all the temp files // Pop off the winning cursor cursor_t* winner = cursor_queue.top(); cursor_queue.pop(); // Grab and emit its message, and advance it emitter.write(std::move(winner->take())); // Put it back in the heap if it is not depleted if (winner->has_next()) { cursor_queue.push(winner); } // TODO: Maybe keep it off the heap for the next loop somehow if it still wins observed_messages++; if (expected_messages != 0) { update_progress(observed_messages); } } // We finished the files, so say we're done. // TODO: Should we warn/fail if we expected the wrong number of messages? update_progress(expected_messages == 0 ? 1 : expected_messages); destroy_progress(); }
static void test_PBM_STEPIT(void) { struct stepit_test { int min; int max; int step; } stepit_tests[] = { { 3, 15, 5 }, { 3, 15, -5 }, { 3, 15, 50 }, { -15, 15, 5 }, { -3, -2, -5 }, { 0, 0, 1 }, { 5, 5, 1 }, { 0, 0, -1 }, { 5, 5, -1 }, { 10, 5, 2 }, }; HWND progress; int i, j; for (i = 0; i < ARRAY_SIZE(stepit_tests); i++) { struct stepit_test *test = &stepit_tests[i]; PBRANGE range; LRESULT ret; progress = create_progress(0); ret = SendMessageA(progress, PBM_SETRANGE32, test->min, test->max); ok(ret != 0, "Unexpected return value.\n"); SendMessageA(progress, PBM_GETRANGE, 0, (LPARAM)&range); ok(range.iLow == test->min && range.iHigh == test->max, "Unexpected range.\n"); SendMessageA(progress, PBM_SETPOS, test->min, 0); SendMessageA(progress, PBM_SETSTEP, test->step, 0); for (j = 0; j < test->max; j++) { int pos = SendMessageA(progress, PBM_GETPOS, 0, 0); int current; pos += test->step; if (test->min != test->max) { if (pos > test->max) pos = (pos - test->min) % (test->max - test->min) + test->min; if (pos < test->min) pos = (pos - test->min) % (test->max - test->min) + test->max; } else pos = test->min; SendMessageA(progress, PBM_STEPIT, 0, 0); current = SendMessageA(progress, PBM_GETPOS, 0, 0); ok(current == pos, "%u: unexpected position %d, expected %d.\n", i, current, pos); } DestroyWindow(progress); } }
void StreamSorter<Message>::stream_sort(istream& stream_in, ostream& stream_out, StreamIndex<Message>* index_to) { // We want to work out the file size, if we can. size_t file_size = 0; { // Save our position auto here = stream_in.tellg(); // Go to the end stream_in.seekg(0, stream_in.end); // Get its position auto there = stream_in.tellg(); // Go back to where we were stream_in.seekg(here); if (stream_in.good()) { // We can seek in this stream. So how far until the end? file_size = there - here; } else { // It's entirely possible that none of that worked. So clear the error flags and leave the size at 0. stream_in.clear(); } } // Don't give an actual 0 to the progress code or it will NaN create_progress("break into sorted chunks", file_size == 0 ? 1 : file_size); // Eventually we put sorted chunks of data in temp files and put their names here vector<string> outstanding_temp_files; // This tracks the number of messages in each file, by file name unordered_map<string, size_t> messages_per_file; // This tracks the total messages observed on input size_t total_messages_read = 0; // This cursor will read in the input file. cursor_t input_cursor(stream_in); #pragma omp parallel shared(stream_in, input_cursor, outstanding_temp_files, messages_per_file, total_messages_read) { while(true) { vector<Message> thread_buffer; #pragma omp critical (input_cursor) { // Each thread fights for the file and the winner takes some data size_t buffered_message_bytes = 0; while (input_cursor.has_next() && buffered_message_bytes < max_buf_size) { // Until we run out of input messages or space, buffer each, recording its size. thread_buffer.emplace_back(std::move(input_cursor.take())); buffered_message_bytes += thread_buffer.back().ByteSizeLong(); } // Update the progress bar update_progress(stream_in.tellg()); } if (thread_buffer.empty()) { // No data was found break; } // Do a sort of the data we grabbed this->sort(thread_buffer); // Save it to a temp file. string temp_name = temp_file::create(); ofstream temp_stream(temp_name); // OK to save as one massive group here. // TODO: This write could also be in a thread. stream::write_buffered(temp_stream, thread_buffer, 0); #pragma omp critical (outstanding_temp_files) { // Remember the temp file name outstanding_temp_files.push_back(temp_name); // Remember the messages in the file, for progress purposes messages_per_file[temp_name] = thread_buffer.size(); // Remember how many messages we found in the total total_messages_read += thread_buffer.size(); } } } // Now we know the reader thmessages have taken care of the input, and all the data is in temp files. destroy_progress(); while (outstanding_temp_files.size() > max_fan_in) { // We can't merge them all at once, so merge subsets of them. outstanding_temp_files = streaming_merge(outstanding_temp_files, &messages_per_file); } // Now we can merge (and maybe index) the final layer of the tree. // Open up cursors into all the files. list<ifstream> temp_ifstreams; list<cursor_t> temp_cursors; open_all(outstanding_temp_files, temp_ifstreams, temp_cursors); // Maintain our own group buffer at a higher scope than the emitter. vector<Message> group_buffer; { // Make an output emitter emitter_t emitter(stream_out); if (index_to != nullptr) { emitter.on_message([&index_to,&group_buffer](const Message& m) { // Copy every message that is emitted. // TODO: Just compute indexing stats instead. group_buffer.push_back(m); }); emitter.on_group([&index_to,&group_buffer](int64_t start_vo, int64_t past_end_vo) { // On every group, tell the index to record the group stats, and clear the buffer. index_to->add_group(group_buffer, start_vo, past_end_vo); group_buffer.clear(); }); } // Merge the cursors into the emitter streaming_merge(temp_cursors, emitter, total_messages_read); } // Clean up temp_cursors.clear(); temp_ifstreams.clear(); for (auto& filename : outstanding_temp_files) { temp_file::remove(filename); } }
int init_panel(window_t *win) { button_t *btn; progress_t *prg; level_t *lvl; slider_t *sld; panel_t *panel = &win->panel; ctx_t *ctx = &panel->ctx; link_initialize(&panel->ctrl.link); list_initialize(&panel->ctrl.child); panel->ctrl.handler = panel_proc; panel->ctrl.parent = (ctrl_t*)win; panel->layout = 0; panel->bitmap.width = 1920; panel->bitmap.height = PANEL_HEIGHT; panel->bitmap.flags = 0; if( create_bitmap(&panel->bitmap) ) { printf("not enough memory for panel bitmap\n"); return 0; } ctx->pixmap = &panel->bitmap; ctx->offset_x = 0; ctx->offset_y = 0; panel->ctrl.ctx = ctx; btn = create_button(NULL, ID_PLAY,0,19,32,32,&panel->ctrl); panel->play_btn = btn; btn->img_default = res_pause_btn; btn->img_hilite = res_pause_btn; btn->img_pressed = res_pause_btn_pressed; btn = create_button(NULL, ID_STOP,0,19,24,24,&panel->ctrl); panel->stop_btn = btn; btn->img_default = res_stop_btn; btn->img_hilite = res_stop_btn; btn->img_pressed = res_stop_btn_pressed; prg = create_progress(NULL,ID_PROGRESS,0,4,0,10,&panel->ctrl); panel->prg = prg; lvl = create_level(NULL, ID_VOL_LEVEL, 0, 20, 96, 10, &panel->ctrl); lvl->vol = -1875; panel->lvl = lvl; sld = create_slider(NULL, ID_VOL_CTRL, 0, 20, 96+12, 12, &panel->ctrl); panel->sld = sld; // btn = create_button(NULL, ID_MINIMIZE,0,5,16,18,(ctrl_t*)cpt); // cpt->minimize_btn = btn; // btn->img_default = res_minimize_btn; // btn->img_hilite = res_minimize_btn_hl; // btn->img_pressed = res_minimize_btn_pressed; update_panel_size(win); return 1; };