diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2020-09-06 09:27:14 +0300 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2020-09-06 09:27:14 +0300 |
commit | 6bd9fbffec920c103d27bf780d60de314316bbd5 (patch) | |
tree | d87aa9226a1a1ed7a6a77652266aae4bbd78cb14 /src/ui/lookupwidget.c | |
parent | 8d249e27e6dda6423af93aa4368a81b13cd3f451 (diff) |
Added a LookupWidget with background thread
Diffstat (limited to 'src/ui/lookupwidget.c')
-rw-r--r-- | src/ui/lookupwidget.c | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/src/ui/lookupwidget.c b/src/ui/lookupwidget.c new file mode 100644 index 00000000..d2550c16 --- /dev/null +++ b/src/ui/lookupwidget.c | |||
@@ -0,0 +1,134 @@ | |||
1 | /* Copyright 2020 Jaakko Keränen <jaakko.keranen@iki.fi> | ||
2 | |||
3 | Redistribution and use in source and binary forms, with or without | ||
4 | modification, are permitted provided that the following conditions are met: | ||
5 | |||
6 | 1. Redistributions of source code must retain the above copyright notice, this | ||
7 | list of conditions and the following disclaimer. | ||
8 | 2. Redistributions in binary form must reproduce the above copyright notice, | ||
9 | this list of conditions and the following disclaimer in the documentation | ||
10 | and/or other materials provided with the distribution. | ||
11 | |||
12 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | ||
13 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
14 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
15 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR | ||
16 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
17 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
18 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||
19 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
20 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
21 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ | ||
22 | |||
23 | #include "lookupwidget.h" | ||
24 | #include "lookup.h" | ||
25 | #include "listwidget.h" | ||
26 | |||
27 | #include <the_Foundation/mutex.h> | ||
28 | #include <the_Foundation/thread.h> | ||
29 | |||
30 | iDeclareType(LookupJob) | ||
31 | |||
32 | struct Impl_LookupJob { | ||
33 | iString term; | ||
34 | iPtrArray results; | ||
35 | }; | ||
36 | |||
37 | static void init_LookupJob(iLookupJob *d) { | ||
38 | init_String(&d->term); | ||
39 | init_PtrArray(&d->results); | ||
40 | } | ||
41 | |||
42 | static void deinit_LookupJob(iLookupJob *d) { | ||
43 | iForEach(PtrArray, i, &d->results) { | ||
44 | delete_LookupResult(i.ptr); | ||
45 | } | ||
46 | deinit_PtrArray(&d->results); | ||
47 | deinit_String(&d->term); | ||
48 | } | ||
49 | |||
50 | iDefineTypeConstruction(LookupJob) | ||
51 | |||
52 | struct Impl_LookupWidget { | ||
53 | iWidget widget; | ||
54 | iListWidget *list; | ||
55 | iThread *work; | ||
56 | iCondition jobAvailable; /* wakes up the work thread */ | ||
57 | iMutex *mtx; | ||
58 | iString nextJob; | ||
59 | iLookupJob *finishedJob; | ||
60 | }; | ||
61 | |||
62 | static iThreadResult worker_LookupWidget_(iThread *thread) { | ||
63 | iLookupWidget *d = userData_Thread(thread); | ||
64 | lock_Mutex(d->mtx); | ||
65 | for (;;) { | ||
66 | wait_Condition(&d->jobAvailable, d->mtx); | ||
67 | if (isEmpty_String(&d->nextJob)) { | ||
68 | break; /* Time to quit. */ | ||
69 | } | ||
70 | iLookupJob *job = new_LookupJob(); | ||
71 | set_String(&job->term, &d->nextJob); | ||
72 | clear_String(&d->nextJob); | ||
73 | unlock_Mutex(d->mtx); | ||
74 | /* Do the lookup. */ { | ||
75 | |||
76 | } | ||
77 | /* Submit the result. */ | ||
78 | lock_Mutex(d->mtx); | ||
79 | if (d->finishedJob) { | ||
80 | /* Previous results haven't been taken yet. */ | ||
81 | delete_LookupJob(d->finishedJob); | ||
82 | } | ||
83 | d->finishedJob = job; | ||
84 | } | ||
85 | unlock_Mutex(d->mtx); | ||
86 | printf("[LookupWidget] worker has quit\n"); fflush(stdout); | ||
87 | return 0; | ||
88 | } | ||
89 | |||
90 | iDefineObjectConstruction(LookupWidget) | ||
91 | |||
92 | void init_LookupWidget(iLookupWidget *d) { | ||
93 | iWidget *w = as_Widget(d); | ||
94 | init_Widget(w); | ||
95 | setId_Widget(w, "lookup"); | ||
96 | setFlags_Widget(w, resizeChildren_WidgetFlag, iTrue); | ||
97 | d->list = addChild_Widget(w, iClob(new_ListWidget())); | ||
98 | d->work = new_Thread(worker_LookupWidget_); | ||
99 | setUserData_Thread(d->work, d); | ||
100 | init_Condition(&d->jobAvailable); | ||
101 | d->mtx = new_Mutex(); | ||
102 | init_String(&d->nextJob); | ||
103 | d->finishedJob = NULL; | ||
104 | } | ||
105 | |||
106 | void deinit_LookupWidget(iLookupWidget *d) { | ||
107 | /* Stop the worker. */ { | ||
108 | iGuardMutex(d->mtx, { | ||
109 | clear_String(&d->nextJob); | ||
110 | signal_Condition(&d->jobAvailable); | ||
111 | }); | ||
112 | join_Thread(d->work); | ||
113 | iRelease(d->work); | ||
114 | } | ||
115 | delete_LookupJob(d->finishedJob); | ||
116 | deinit_String(&d->nextJob); | ||
117 | delete_Mutex(d->mtx); | ||
118 | deinit_Condition(&d->jobAvailable); | ||
119 | } | ||
120 | |||
121 | static void draw_LookupWidget_(const iLookupWidget *d) { | ||
122 | const iWidget *w = constAs_Widget(d); | ||
123 | draw_Widget(w); | ||
124 | } | ||
125 | |||
126 | static iBool processEvent_LookupWidget_(iLookupWidget *d, const SDL_Event *ev) { | ||
127 | iWidget *w = as_Widget(d); | ||
128 | return processEvent_Widget(w, ev); | ||
129 | } | ||
130 | |||
131 | iBeginDefineSubclass(LookupWidget, Widget) | ||
132 | .draw = (iAny *) draw_LookupWidget_, | ||
133 | .processEvent = (iAny *) processEvent_LookupWidget_, | ||
134 | iEndDefineSubclass(LookupWidget) | ||