1
1
#include "watcher.h"
2
2
3
- static void Wprintf (const int err , const char * fmt , ...) {
3
+ static void Wprintf (const char * fmt , ...) {
4
4
5
5
char buf [WATCHER_BUFSIZE ];
6
6
va_list arg_ptr ;
@@ -9,11 +9,11 @@ static void Wprintf(const int err, const char *fmt, ...) {
9
9
int bytes = vsnprintf (buf , WATCHER_BUFSIZE , fmt , arg_ptr );
10
10
va_end (arg_ptr );
11
11
12
- if (write (err ? STDERR_FILENO : STDOUT_FILENO , buf , (size_t ) bytes )) {};
12
+ if (write (STDOUT_FILENO , buf , (size_t ) bytes )) {};
13
13
14
14
}
15
15
16
- void session_finalizer (SEXP xptr ) {
16
+ static void session_finalizer (SEXP xptr ) {
17
17
if (R_ExternalPtrAddr (xptr ) == NULL ) return ;
18
18
FSW_HANDLE handle = (FSW_HANDLE ) R_ExternalPtrAddr (xptr );
19
19
fsw_stop_monitor (handle );
@@ -22,38 +22,53 @@ void session_finalizer(SEXP xptr) {
22
22
23
23
void (* eln2 )(void (* )(void * ), void * , double , int ) = NULL ;
24
24
25
- void load_later_safe (void * data ) {
26
- (void ) data ;
27
- SEXP fn , call ;
28
- fn = Rf_install ("loadNamespace" );
25
+ static void load_later_safe (void * data ) {
26
+ SEXP call , fn = (SEXP ) data ;
29
27
PROTECT (call = Rf_lang2 (fn , Rf_mkString ("later" )));
30
28
Rf_eval (call , R_GlobalEnv );
31
29
UNPROTECT (1 );
32
30
}
33
31
34
- void exec_later (void * data ) {
32
+ static void exec_later (void * data ) {
35
33
SEXP call , fn = (SEXP ) data ;
36
34
PROTECT (call = Rf_lcons (fn , R_NilValue ));
37
35
Rf_eval (call , R_GlobalEnv );
38
36
UNPROTECT (1 );
39
37
}
40
38
41
- void process_events (fsw_cevent const * const events , const unsigned int event_num , void * data ) {
39
+ // custom non-allocating version of fsw_get_event_flag_name() handling main types
40
+ static void get_event_flag_name (const int flag , char * buf ) {
41
+ const char * name ;
42
+ switch (flag ) {
43
+ case 1 << 1 : name = "Created" ; break ;
44
+ case 1 << 2 : name = "Updated" ; break ;
45
+ case 1 << 3 : name = "Removed" ; break ;
46
+ case 1 << 4 : name = "Renamed" ; break ;
47
+ default : name = "Unknown" ; break ;
48
+ }
49
+ memcpy (buf , name , strlen (name ));
50
+ }
51
+
52
+ static void process_events (fsw_cevent const * const events , const unsigned int event_num , void * data ) {
42
53
if (data != R_NilValue && eln2 != NULL ) {
43
54
eln2 (exec_later , data , 0 , 0 );
44
55
} else {
45
- for (unsigned int i = 0 ; i < event_num ; i ++ )
46
- for (unsigned int j = 0 ; j < events [i ].flags_num ; j ++ )
47
- Wprintf (0 , "Event: %s\n Flag: %s\n" , events [i ].path , fsw_get_event_flag_name (events [i ].flags [j ]));
56
+ char buf [8 ]; // large enough for subset of events handled by get_event_flag_name()
57
+ memset (buf , 0 , sizeof (buf ));
58
+ for (unsigned int i = 0 ; i < event_num ; i ++ ) {
59
+ for (unsigned int j = 0 ; j < events [i ].flags_num ; j ++ ) {
60
+ get_event_flag_name (events [i ].flags [j ], buf );
61
+ Wprintf ("Event: %s\n Flag: %s\n" , events [i ].path , buf );
62
+ }
63
+ }
48
64
}
49
65
}
50
66
51
- void * watcher_thread (void * args ) {
67
+ static void * watcher_thread (void * args ) {
52
68
53
- pthread_detach (pthread_self ());
54
69
FSW_HANDLE handle = (FSW_HANDLE ) args ;
55
70
fsw_start_monitor (handle );
56
- return ( void * ) NULL ;
71
+ return NULL ;
57
72
58
73
}
59
74
@@ -84,6 +99,7 @@ SEXP watcher_create(SEXP path, SEXP recursive, SEXP callback) {
84
99
Rf_error ("Failed to set watch callback" );
85
100
}
86
101
102
+ // filter only for main event types: Created, Updated, Removed, Renamed
87
103
fsw_event_type_filter filter ;
88
104
for (int flag = Created ; flag <= Renamed ; flag = flag << 1 ) {
89
105
filter .flag = flag ;
@@ -106,12 +122,18 @@ SEXP watcher_start_monitor(SEXP session) {
106
122
107
123
FSW_HANDLE handle = (FSW_HANDLE ) R_ExternalPtrAddr (session );
108
124
pthread_t thr ;
125
+ pthread_attr_t attr ;
126
+
127
+ pthread_attr_init (& attr );
128
+ pthread_attr_setdetachstate (& attr , PTHREAD_CREATE_DETACHED );
109
129
110
- if (eln2 == NULL && R_ToplevelExec (load_later_safe , NULL )) {
130
+ if (eln2 == NULL && R_ToplevelExec (load_later_safe , ( void * ) Rf_install ( "loadNamespace" ) )) {
111
131
eln2 = (void (* )(void (* )(void * ), void * , double , int )) R_GetCCallable ("later" , "execLaterNative2" );
112
132
}
133
+ const int ret = pthread_create (& thr , & attr , & watcher_thread , handle );
134
+ pthread_attr_destroy (& attr );
113
135
114
- return Rf_ScalarLogical (pthread_create ( & thr , NULL , & watcher_thread , handle ) == 0 );
136
+ return Rf_ScalarLogical (ret == 0 );
115
137
116
138
}
117
139
0 commit comments