1
  
2
  
3
  
4
  
5
  
6
  
7
  
8
  
9
  
10
  
11
  
12
  
13
  
14
  
15
  
16
  
17
  
18
  
19
  
20
  
21
  
22
  
23
  
24
  
25
  
26
  
27
  
28
  
29
  
30
  
31
  
32
  
33
  
34
  
35
  
36
  
37
  
38
  
39
  
40
  
41
  
42
  
43
  
44
  
45
  
46
  
47
  
48
  
49
  
50
  
51
  
52
  
53
  
54
  
55
  
56
  
57
  
58
  
59
  
60
  
61
  
62
  
63
  
64
  
65
  
66
  
67
  
68
  
69
  
#pike __REAL_VERSION__ 
#require constant(System.FSEvents.EventStream) 
 
//! A variation of @[EventStream] that provides a blocking interface. 
//! 
//! @note 
//!   A quirk of the underlying IO subsystem in CoreFoundation is that 
//!   there is exactly one runloop per thread. Because FSEvents uses 
//!   CoreFoundation, this means that there's no meaningful way to 
//!   specify which backend should process these events. Therefore, 
//!   always make sure that the thread you create the EventStream 
//!   object is the same one you read events from, otherwise 
//!   @[read_event] will run not run the EventLoop that this 
//!   EventStream is registered with, resulting in events never being 
//!   delivered. 
 
  inherit .EventStream; 
 
  protected ADT.Queue received_events = ADT.Queue(); 
 
  protected void bfse_callback(string path, int flags, int event_id) 
  { 
    received_events->put((["path": path, "flags": flags, "event_id": event_id])); 
  } 
 
//! 
  protected void create(array(string) paths, float latency, int|void since_when, int|void flags) 
  { 
#if !constant(Pike.DefaultBackend.HAVE_CORE_FOUNDATION) 
    throw(Error.Generic("Pike does not have support for Core Foundation. FSEvents will not function!\n")); 
#endif 
    ::create(paths, latency, since_when, flags); 
    ::set_callback(bfse_callback); 
  } 
 
  void set_callback(function(:void) callback) 
  { 
    throw(Error.Generic("BlockingEventStream does not support set_callback().\n")); 
  } 
 
  //! wait for an event to be received, and return it. 
  //! 
  //! @param timeout 
  //!   an optional limit to the amount of time we're willing to wait 
  mixed read_event(void|float timeout) 
  { 
    int|float res; 
    float orig_timeout = timeout; 
    if(!is_started()) 
    { 
      Pike.DefaultBackend.enable_core_foundation(1); 
      start(); 
    } 
 
    if(received_events->is_empty()) 
    { 
      do 
      { 
        res = Pike.DefaultBackend(timeout); 
      } while(floatp(res) && received_events->is_empty() && orig_timeout && (timeout = (timeout-res)) > 0.0); 
    } 
 
    if(received_events->is_empty()) 
      return 0; 
    else 
      return received_events->get(); 
  }