Browse code

Prioritize loading image under cursor. Use sleep in background thread. Use nanosleep instead of select for sleeping.

Dario Rodriguez authored on 28/09/2025 11:09:14
Showing 6 changed files
... ...
@@ -16,6 +16,7 @@
16 16
 #include <unistd.h>
17 17
 #include <string.h>
18 18
 #include <pthread.h>
19
+#include <sys/time.h>
19 20
 #if !defined(__linux__) && !defined(ANDROID)
20 21
 #include "win32_pipe.h"
21 22
 #endif
... ...
@@ -25,25 +26,20 @@
25 26
 #include "bg.h"
26 27
 
27 28
 #define UNLOADTIMEOUTSECONDS 10
29
+#define THREADNUMBER 8
28 30
 
29
-static int mypipe(int fds[2]);
30
-static int mypiperead(int fd, char *buf, int count);
31
-static int mypipewrite(int fd, char *buf, int count);
31
+static int mysleep(struct timeval *tv);
32 32
 
33 33
 void
34 34
 bg_staticinit(void)
35 35
 {
36
-#if !defined(__linux__) && !defined(ANDROID)
37
-        win32pipe_init();
38
-#endif
36
+        /* not needed now, was for win32pipe_init() */
39 37
 }
40 38
 
41 39
 void
42 40
 bg_staticfini(void)
43 41
 {
44
-#if !defined(__linux__) && !defined(ANDROID)
45
-        win32pipe_fini();
46
-#endif
42
+        /* not needed now, was for win32pipe_fini() */
47 43
 }
48 44
 
49 45
 bg_t *
... ...
@@ -54,9 +50,6 @@ bg_init(int sizebgload)
54 50
         bg=NULL;
55 51
         if((errstr="Insuf. mem. for bg")==NULL
56 52
           || (bg=calloc(1,sizeof(bg_t)))==NULL
57
-          || (errstr="Error init pipes (please check program is not blocked in firewall)")==NULL
58
-          || (bg->pipe[0]=bg->pipe[1]=-1)!=-1
59
-          || mypipe(bg->pipe)!=0
60 53
           || (errstr="Insuf mem bgload")==NULL
61 54
           || (bg->bgload=calloc(sizebgload,sizeof(bgload_t)))==NULL
62 55
           || (bg->sizebgload=sizebgload)!=sizebgload
... ...
@@ -81,11 +74,7 @@ bg_free(bg_t *bg)
81 74
         if(bg==NULL)
82 75
                 return; /* nothing to do */
83 76
         if(bg->flag_threadstarted) {
84
-                char dummy=1;
85
-#if 1
86
-fprintf(stderr,"bg_free: notifying thread to exit\n");
87
-#endif
88
-                mypipewrite(bg->pipe[WR],&dummy,1);
77
+                bg->do_exit=1;
89 78
 #if 1
90 79
 fprintf(stderr,"bg_free: joining thread\n");
91 80
 #endif
... ...
@@ -94,11 +83,8 @@ fprintf(stderr,"bg_free: joining thread\n");
94 83
 fprintf(stderr,"bg_free: thread joined OK\n");
95 84
 #endif
96 85
                 bg->flag_threadstarted=0;
86
+                bg->do_exit=0;
97 87
         }
98
-        if(bg->pipe[0]!=-1)
99
-                close(bg->pipe[0]),bg->pipe[0]=-1;
100
-        if(bg->pipe[1]!=-1)
101
-                close(bg->pipe[1]),bg->pipe[1]=-1;
102 88
         if(bg->bgload!=NULL) {
103 89
                 bgload_t *bgload;
104 90
                 for(i=0,bgload=bg->bgload;i<bg->sizebgload;i++,bgload++) {
... ...
@@ -148,7 +134,6 @@ bg_add(bg_t *bg, char *path)
148 134
 {
149 135
         int i;
150 136
         bgload_t *bgload;
151
-        char dummy;
152 137
         if(bg==NULL)
153 138
                 return(-1);
154 139
         for(i=0,bgload=bg->bgload;i<bg->sizebgload;i++,bgload++) {
... ...
@@ -156,8 +141,6 @@ bg_add(bg_t *bg, char *path)
156 141
                         bgload->is_todo=1;
157 142
                         bgload->has_mark=1;
158 143
                         gettimeofday(&(bgload->tv_lastadded),NULL); // Breaks premise of "don't touch until thread finished", but this is rather innocuous
159
-                        dummy=0;
160
-                        mypipewrite(bg->pipe[WR],&dummy,1);
161 144
                         return(0); /* already on list */
162 145
                 }
163 146
         }
... ...
@@ -169,9 +152,7 @@ bg_add(bg_t *bg, char *path)
169 152
                         bgload->is_todo=1;
170 153
                         bgload->has_mark=1;
171 154
                         gettimeofday(&(bgload->tv_lastadded),NULL); // Breaks premise of "don't touch until thread finished", but this is rather innocuous
172
-                        dummy=0;
173 155
                         bgload->lended_to_thread=1;
174
-                        mypipewrite(bg->pipe[WR],&dummy,1);
175 156
                         return(0); /* added to list */
176 157
                 }
177 158
         }
... ...
@@ -213,16 +194,11 @@ void *
213 194
 bg_thread(void *parambg)
214 195
 {
215 196
         bg_t *bg;
216
-        char dummy;
217 197
         bg=(bg_t *)parambg;
218 198
         int i;
219 199
         bgload_t *bgload,*candidate;
220 200
         while(1) {
221
-                mypiperead(bg->pipe[RD],&dummy,1);
222
-#if 1
223
-fprintf(stderr,"Thread received byte: %i\n",(int)((unsigned char)dummy));
224
-#endif
225
-                if(dummy!=0)
201
+                if(bg->do_exit!=0)
226 202
                         break; /* was told to exit */
227 203
                 for(candidate=NULL,i=0,bgload=bg->bgload;i<bg->sizebgload;i++,bgload++) {
228 204
                         if(bgload->lended_to_thread==0)
... ...
@@ -249,53 +225,35 @@ fprintf(stderr,"Thread received byte: %i\n",(int)((unsigned char)dummy));
249 225
                                 bgload->has_failedload=1;
250 226
                         bgload->lastused=time(NULL);
251 227
                         bgload->thread_finished=1;
228
+                } else {
229
+                        struct timeval tv;
230
+                        tv.tv_sec=0,tv.tv_usec=50*1000; /* sleep 50ms if nothing to do */
231
+                        mysleep(&tv);
252 232
                 }
233
+#if 1
234
+fprintf(stderr,"."),fflush(stderr);
235
+#endif
253 236
         }
254 237
         pthread_exit(NULL);
255 238
         return(NULL);
256 239
 }
257 240
 
258
-
259
-
260 241
 #if !defined(__linux__) && !defined(ANDROID)
261 242
 static int
262
-mypipe(int fds[2])
263
-{
264
-        return(win32pipe_pipe(fds));
265
-}
266
-
267
-static int
268
-mypiperead(int fd, char *buf, int count)
269
-{
270
-        return(win32pipe_read(fd,buf,count));
271
-}
272
-
273
-static int
274
-mypipewrite(int fd, char *buf, int count)
243
+mysleep(struct timeval *tv)
275 244
 {
276
-        return(win32pipe_write(fd,buf,count));
245
+        win32pipe_sleep(tv->tv_sec*1000+tv->tv_usec/1000);
246
+        return(0);
277 247
 }
278 248
 #else
279 249
 static int
280
-mypipe(int fds[2])
281
-{
282
-        return(pipe(fds));
283
-}
284
-
285
-static int
286
-mypiperead(int fd, char *buf, int count)
287
-{
288
-        return(read(fd,buf,count));
289
-}
290
-
291
-static int
292
-mypipewrite(int fd, char *buf, int count)
250
+mysleep(struct timeval *tv)
293 251
 {
294
-        return(write(fd,buf,count));
252
+        struct timespec ts;
253
+        if(tv==NULL)
254
+                return(-1);
255
+        ts.tv_sec=tv->tv_sec,ts.tv_nsec=tv->tv_usec*1000;
256
+        nanosleep(&ts,NULL);
257
+        return(0);
295 258
 }
296 259
 #endif
297
-
298
-
299
-
300
-
301
-
... ...
@@ -16,7 +16,6 @@
16 16
 #ifndef BG_H
17 17
 #define BG_H
18 18
 
19
-#include <pthread.h>
20 19
 #include <time.h>
21 20
 #include <sys/time.h>
22 21
 #include "raylib.h"
... ...
@@ -39,10 +38,10 @@ typedef struct bgload_t {
39 38
 typedef struct bg_t {
40 39
         int sizebgload;
41 40
         bgload_t *bgload;
42
-        int pipe[2];
43 41
         pthread_t thread;
44 42
         pthread_attr_t tattr;
45 43
         int flag_threadstarted;
44
+        int do_exit;
46 45
 } bg_t;
47 46
 
48 47
 
... ...
@@ -35,7 +35,7 @@
35 35
 #define SCROLLTHRESHOLD (LEFTIMAGESIDELEN/3)
36 36
 #define WHEELSTEP LEFTIMAGESIDELEN
37 37
 #define SEP '/'
38
-#define SIZEBGLOAD 256
38
+#define SIZEBGLOAD (3*((DEFAULTWIDTH+(LEFTIMAGESIDELEN-1))/LEFTIMAGESIDELEN)*((DEFAULTHEIGHT+(LEFTIMAGESIDELEN-1))/LEFTIMAGESIDELEN))
39 39
 #define DEFAULTDIRDATAHEIGHT 492
40 40
 #define ADDREMOVEDIRDATAHEIGHT 128
41 41
 #define UTF8DOWNARROW "\xe2\x86\x86" /* U+2186 in UTF-8 */
... ...
@@ -45,7 +45,13 @@
45 45
 #define BLOCKDIRDATA 16
46 46
 
47 47
 #define MYFUNC "UNKNOWN"
48
+#if 0
48 49
 #define IMDEBUG(a) fprintf(stderr,"%s:%i: %s: %s\n",__FILE__,__LINE__,MYFUNC,a)
50
+#define IMDEBUG2(a) fprintf(stderr,"%s:%i: %s: ",__FILE__,__LINE__,MYFUNC),fprintf a
51
+#else
52
+#define IMDEBUG(a)
53
+#define IMDEBUG2(a)
54
+#endif
49 55
 
50 56
 // RIGHTSIDEMARGIN=FONTBIGSIZE/2
51 57
 
... ...
@@ -495,6 +501,7 @@ im_body_draw(body_t *body, mousedata_t *mousedata, int windowwidth, int windowhe
495 501
         int xoff,yoff;
496 502
         thumb_t *thumb;
497 503
         char statustooltip[1024];
504
+        char imageundermouse[1024];
498 505
         thumb_t *selectedthumb;
499 506
         IMDEBUG("Pre-sanitycheck");
500 507
         if(body==NULL)
... ...
@@ -549,18 +556,15 @@ im_body_draw(body_t *body, mousedata_t *mousedata, int windowwidth, int windowhe
549 556
                 rayui_scrollablerectadd(body->rayui,mousedata,&whxy,"body.leftside",body->dirdata[body->currentdirdata]->leftscrollpos,(int (*)(void *, Vector2))im_body_tryselect,body,SCROLLTHRESHOLD);
550 557
         }
551 558
         DrawRectangle(body->whxy.x,body->whxy.y,body->leftsize, body->whxy.h, (Color){ 215, 215, 215, 255 } );
552
-fprintf(stderr,"%ix%i+%i+%i\n",body->leftsize, body->whxy.h,body->whxy.x,body->whxy.y);
559
+        IMDEBUG2((stderr,"%ix%i+%i+%i\n",body->leftsize, body->whxy.h,body->whxy.x,body->whxy.y));
553 560
         /* draw right side background */
554
-#if 1
555
-fprintf(stderr,"body->whxy:%ix%i+%i+%i\n",UNROLLWHXY(body->whxy));
556
-fprintf(stderr,"body->leftsize:%i\n",body->leftsize);
557
-#endif
561
+        IMDEBUG2((stderr,"body->whxy:%ix%i+%i+%i\n",UNROLLWHXY(body->whxy)));
562
+        IMDEBUG2((stderr,"body->leftsize:%i\n",body->leftsize));
558 563
         IMDEBUG("draw right bg");
559 564
         DrawRectangle(body->whxy.x+body->leftsize,body->whxy.y,body->whxy.w-body->leftsize, body->whxy.h, (Color){ 227, 227, 227, 255 } );
560
-fprintf(stderr,"DrawRectangle(body->whxy.x(%i)+body->leftsize(%i),body->whxy.y(%i),body->whxy.w(%i)-body->leftsize(%i), body->whxy.h(%i), (Color){ 227, 227, 227, 255 } );\n"
561
-        ,body->whxy.x,body->leftsize,body->whxy.y,body->whxy.w,body->leftsize, body->whxy.h);
562
-
563
-fprintf(stderr,"%ix%i+%i+%i\n",body->whxy.w-body->leftsize, body->whxy.h,body->whxy.x+body->leftsize,body->whxy.y);
565
+        IMDEBUG2((stderr,"DrawRectangle(body->whxy.x(%i)+body->leftsize(%i),body->whxy.y(%i),body->whxy.w(%i)-body->leftsize(%i), body->whxy.h(%i), (Color){ 227, 227, 227, 255 } );\n"
566
+        ,body->whxy.x,body->leftsize,body->whxy.y,body->whxy.w,body->leftsize, body->whxy.h));
567
+        IMDEBUG2((stderr,"%ix%i+%i+%i\n",body->whxy.w-body->leftsize, body->whxy.h,body->whxy.x+body->leftsize,body->whxy.y));
564 568
         /* reset lazy load marks */
565 569
         bg_resetmarks(body->bg);
566 570
         /* first pass, draw leftside, second pass, draw all of rightside */
... ...
@@ -648,6 +652,7 @@ DrawRectangle(UNROLLXYWH(body->backwhxy),((Color){ 0,255,0,255 })); /* hit zone
648 652
                                 FILLWHXY(thumb->screenwhxy,0,0,0,0);
649 653
                         }
650 654
                         /* files */
655
+                        imageundermouse[0]='\0';
651 656
                         for(k=0,lastx=lasty=0;k<dirdata->listing.usedelems;k++) {
652 657
                                 Texture2D *te;
653 658
                                 whxy_t *whxy;
... ...
@@ -669,6 +674,10 @@ DrawRectangle(UNROLLXYWH(body->backwhxy),((Color){ 0,255,0,255 })); /* hit zone
669 674
                                 /* show image */
670 675
                                 has_imagedrawn=0;
671 676
                                 if(is_imagefilename(elem->name+1) && !(thumb->screenwhxy.y>(body->whxy.y+body->whxy.h) || (thumb->screenwhxy.y+thumb->screenwhxy.h)<body->whxy.y)) {
677
+                                        if(is_global_insidewhxy(mousedata->mousepos,&(thumb->screenwhxy),0)) {
678
+                                                snprintf(imageundermouse,sizeof(imageundermouse),"%s/%s/%s",body->rootdir,dirdata->dirname,elem->name+1);
679
+                                                imageundermouse[sizeof(imageundermouse)-1]='\0';
680
+                                        }
672 681
                                         if(thumb->has_texture==0 && thumb->has_failedload==0) {
673 682
                                                 bgload_t *bgload;
674 683
                                                 char fullpath[2048];
... ...
@@ -774,6 +783,8 @@ fprintf(stderr,"elem:\"%s\" sidelen:%i old:%ix%i new:%ix%i\n",elem->name+1,sidel
774 783
                                         selectedthumb=thumb;
775 784
                                 }
776 785
                         }
786
+                        if(imageundermouse[0]!='\0')
787
+                                bg_add(body->bg,imageundermouse); /* to prioritise loading this image */
777 788
                         for(;k<dirdata->listing.usedelems;k++) {
778 789
                                 elem=dirdata->listing.elems+k;
779 790
                                 if(elem->name[0]!='f' && elem->name[0]!='l')
... ...
@@ -176,6 +176,10 @@ rayui_getmousedata(rayui_t *rayui, mousedata_t *mousedata)
176 176
           )?1:0;
177 177
         mousedata->needs_nextredraw=0;
178 178
         /* mouse process scrolling */
179
+#if 1
180
+if(mousedata->lmbdown!=mousedata->oldlmbdown)
181
+ fprintf(stderr,"[%s:+%i+%i] ===\n",(mousedata->lmbdown==1)?"DOWN":".UP.",(int)mousedata->mousepos.x,(int)mousedata->mousepos.y);
182
+#endif
179 183
         if(mousedata->lmbdown==1 && mousedata->oldlmbdown==0 && mousedata->scrollstart==0) {
180 184
                 for(i=0;i<mousedata->usedscrollablerect;i++) {
181 185
                         if(is_global_insidewhxy(mousedata->mousepos,&(mousedata->scrollablerect[i].whxy),0)) {
... ...
@@ -187,7 +191,17 @@ rayui_getmousedata(rayui_t *rayui, mousedata_t *mousedata)
187 191
                                 break;
188 192
                         }
189 193
                 }
194
+#if 1
195
+if(i>=mousedata->usedscrollablerect) {
196
+fprintf(stderr,"Couldn't start scrolling because not in scrollable area\n");
197
+}
198
+#endif
190 199
         }
200
+#if 1
201
+else if(mousedata->lmbdown==1 && mousedata->oldlmbdown==0 && mousedata->scrollstart!=0) {
202
+fprintf(stderr,"Couldn't start scrolling because scrollstart!=0\n");
203
+}
204
+#endif
191 205
         if(mousedata->scrollstart!=0 && mousedata->lmbdown==0) {
192 206
                 mousedata->scrollstart=0;
193 207
                 if(mousedata->is_scrolling)
... ...
@@ -1,5 +1,6 @@
1 1
 #if !defined(__linux__) && !defined(ANDROID)
2 2
 #include <winsock2.h>
3
+#include <synchapi.h>
3 4
 typedef SOCKET socket_t; /* https://stackoverflow.com/questions/10817252/why-is-invalid-socket-defined-as-0-in-winsock2-h-c */
4 5
 #ifndef SHUT_WR
5 6
 #define SHUT_WR SD_SEND
... ...
@@ -147,4 +148,10 @@ win32pipe_write(int fd, char *buf, int count)
147 148
         return(send(fd,buf,count,0));
148 149
 }
149 150
 
151
+int
152
+win32pipe_sleep(int ms)
153
+{
154
+       Sleep(ms);
155
+       return(0);
156
+}
150 157
 
... ...
@@ -3,5 +3,7 @@ void win32pipe_fini(void);
3 3
 int win32pipe_pipe(int fds[2]);
4 4
 int win32pipe_read(int fd, char *buf, int count);
5 5
 int win32pipe_write(int fd, char *buf, int count);
6
+int win32pipe_sleep(int ms); /* does not require calling win32pipe_init()/win32pipe_fini() */
7
+
6 8
 
7 9