summaryrefslogtreecommitdiff
path: root/sql/my_apc.h
blob: 3906aa24408c9e389b2f03e257210566ee6fda34 (plain)
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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
/*
  TODO: MP AB Copyright
*/

/*
  Design
  - Mutex-guarded request queue (it belongs to the target), which can be enabled/
    disabled (when empty).

  - After the request has been put into queue, the requestor waits for request
    to be satisfied. The worker satisifes the request and signals the
    requestor.
*/

/*
  Target for asynchronous calls.
*/
class Apc_target
{
public:
  Apc_target() : enabled(0), apc_calls(NULL) /*, call_queue_size(0)*/ {} 
  ~Apc_target() { DBUG_ASSERT(!enabled && !apc_calls);}

  /* 
    Initialize the target. This must be called before anything else. Right
    after initialization, the target is disabled.
  */
  void init();

  /* 
    Destroy the target. The target must be disabled when this call is made.
  */
  void destroy();
  
  /* 
    Enter into state where this target will be serving APC requests
  */
  void enable();

  /* 
    Leave the state where we could serve APC requests (will serve all already 
    enqueued requests)
  */
  void disable();
  
  /*
    This should be called periodically to serve observation requests.
  */
  void process_apc_requests();

  typedef void (*apc_func_t)(void *arg);
  
  /*
    Make an APC call: schedule it for execution and wait until the target
    thread has executed it. This function must not be called from a thread
    that's different from the target thread.

    @retval FALSE - Ok, the call has been made
    @retval TRUE  - Call wasnt made (either the target is in disabled state or
                    timeout occured)
  */
  bool make_apc_call(apc_func_t func, void *func_arg, 
                     int timeout_sec, bool *timed_out);

#ifndef DBUG_OFF
  int n_calls_processed;
  //int call_queue_size;
#endif
private:
  class Call_request;
  int enabled;

  Call_request *apc_calls;
  pthread_mutex_t LOCK_apc_queue;


  class Call_request
  {
  public:
    apc_func_t func;
    void *func_arg;
    bool done;

    pthread_mutex_t LOCK_request;
    pthread_cond_t COND_request;

    Call_request *next;
    Call_request *prev;
    
    const char *what;
  };

  void enqueue_request(Call_request *qe);
  void dequeue_request(Call_request *qe);
  Call_request *get_first_in_queue()
  { 
    return apc_calls;
  }
};

///////////////////////////////////////////////////////////////////////