Merge remote-tracking branch 'origin/0.10'
[platform/upstream/gstreamer.git] / docs / random / wtay / poll-timeout
1 WITH LOCK
2 *********
3
4 create clock id:
5
6   id->state = OK;
7
8
9 waiting for id:
10
11    lock
12    /* once unscheduled, the id cannot be used anymore */
13    while (id->state != unscheduled) {
14      id->state = busy;
15      unlock
16
17      ret = gstpoll (timeout);
18
19      lock
20      if (id->state == unscheduled) {
21        /* id became unscheduled, read the fd and broadcast */
22        read (fd)
23        cond_broadcast ()
24      }
25      else {
26        if (ret != 0) {
27          /* some other id got unlocked */ 
28          /* mark ourselves as EARLY, we release the lock and we could be
29           * unscheduled ourselves but we don't want the unscheduling thread
30           * to write on the fd */
31          id->state = EARLY;
32          /* wait until it reads the fd and signals us */
33          cond_wait ()
34        }
35        else {
36          /* we timed out */
37          id->state = OK | EARLY;
38        }
39      }
40    }
41    unlock
42    return id->state;
43
44
45 unschedule id:
46
47    lock
48    /* if it's busy waiting in poll, write to the fd */
49    if (id->state == busy) {
50      write (fd)
51    }
52    /* when it leaves the poll, it'll detect the unscheduled. */
53    id->state = unscheduled;
54    unlock
55
56
57
58 ATOMIC
59 ******
60
61 create clock id:
62
63   id->state = OK;
64
65
66 waiting for id:
67
68    /* once state changes to != OK, the id cannot be used anymore */
69    while (g_atomic_int_compare_and_exchange (&id->state, OK, BUSY) {
70
71      ret = gstpoll (timeout);
72
73      /* two things can happen here, either the entry is BUSY or UNSCHEDULED,
74       * first check if it was busy. */
75      if (g_atomic_int_compare_and_exchange (&id->state, BUSY, OK) {
76        /* we got unscheduled, see if it was because we timed out or some other
77         * id got unscheduled */
78        if (ret != 0) {
79          if (g_atomic_int_get (&waiters) > 0) {
80            lock
81            /* some other id got unlocked */ 
82            /* wait until it reads the fd and signals us */
83            while (waiters) 
84              cond_wait ()
85            unlock
86          }
87        }
88        else {
89          /* we timed out update the status. */
90          id->state = OK | EARLY;
91          break;
92        }
93      }
94      else if (g_atomic_int_get (&id->state) == UNSCHEDULED) {
95        /* id became unscheduled, read the fd and broadcast */
96        lock
97        read (fd)
98        g_atomic_int_dec (&waiters);
99        cond_broadcast ()
100        unlock
101        break;
102      }
103      else {
104        g_assert_not_reached ();
105      }
106    }
107
108    return id->state;
109
110
111 unschedule id:
112
113    if (g_atomic_int_compare_and_exchange (&id->state, BUSY, UNSCHEDULED) {
114      /* if it's busy waiting in poll, write to the fd */
115      lock
116      g_atomic_int_inc (&waiters)
117      write (fd)
118      unlock
119    }
120    else {
121      /* was not waiting, just mark unscheduled */
122      g_atomic_int_set (id->state, UNSCHEDULED);
123    }