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
  
//! 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->write((["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.GOT_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()) 
    { 
      get_backend()->enable_core_foundation(1); 
      start(); 
    } 
 
    if(received_events->is_empty()) 
    { 
      do 
      { 
        res = get_backend()(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(); 
  }