File: _kievents_wait_unix.c

package info (click to toggle)
python-kinterbasdb 3.1-1
  • links: PTS
  • area: main
  • in suites: sarge
  • size: 1,044 kB
  • ctags: 1,157
  • sloc: ansic: 6,879; python: 2,517; makefile: 77
file content (147 lines) | stat: -rw-r--r-- 4,414 bytes parent folder | download | duplicates (2)
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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/* KInterbasDB Python Package - Implementation of Event Waiting - UNIX
**
** Version 3.1
**
** The following contributors hold Copyright (C) over their respective
** portions of code (see license.txt for details):
**
** [Original Author (maintained through version 2.0-0.3.1):]
**   1998-2001 [alex]  Alexander Kuznetsov   <alexan@users.sourceforge.net>
** [Maintainers (after version 2.0-0.3.1):]
**   2001-2002 [maz]   Marek Isalski         <kinterbasdb@maz.nu>
**   2002-2004 [dsr]   David Rushby          <woodsplitter@rocketmail.com>
** [Contributors:]
**   2001      [eac]   Evgeny A. Cherkashin  <eugeneai@icc.ru>
**   2001-2002 [janez] Janez Jere            <janez.jere@void.si>
*/

/* This source file is designed to be directly included in _kievents.c,
** without the involvement of a header file. */

/************************* PUBLIC FUNCTIONS:BEGIN ****************************/

PlatformEventType platform_create_event_object() {
  /* We use kimem_plain_malloc here rather than kimem_main_malloc because it's
  ** not safe to assume the GIL is held. */
  platform_event_struct *event = kimem_plain_malloc(sizeof(platform_event_struct));

  if (event == NULL) {
    goto PLATFORM_CREATE_EVENT_OBJECT_FAILED;
  }

  memset( (void *) event, '\0', sizeof(platform_event_struct));

  if ( pthread_mutex_init(&event->mutex, NULL) != 0 ) {
    goto PLATFORM_CREATE_EVENT_OBJECT_FAILED;
  }

  if ( pthread_cond_init(&event->cond, NULL) != 0 ) {
    goto PLATFORM_CREATE_EVENT_OBJECT_FAILED;
  }

  return event;

PLATFORM_CREATE_EVENT_OBJECT_FAILED:
  platform_free_event_object(event);
  return NULL;
} /* platform_create_event_object */


void platform_free_event_object(PlatformEventType event) {
  if (event == NULL) {
    return;
  }

  if (&event->mutex != NULL) {
    /* YYY: Perhaps should trylock+unlock before destroying? */
    pthread_mutex_destroy(&event->mutex);
  }
  if (&event->cond != NULL) {
    pthread_cond_destroy(&event->cond);
  }

  /* We use kimem_plain_free here rather than kimem_main_free because it's
  ** not safe to assume the GIL is held (even if there GIL were held *right
  ** here*, we'd still have to use kimem_plain_free because the memory was
  ** allocated with kimem_plain_malloc). */
  kimem_plain_free(event);
} /* platform_free_event_object */


int event_queue_wait(EventQueue *queue, long timeout_millis) {
  PlatformEventType event = queue->event;
  int wait_result;

  if ( pthread_mutex_lock(&event->mutex) != 0 ) {
    return EVENT_ERROR;
  }

  if (timeout_millis == (long) WAIT_INFINITELY) {
    wait_result = pthread_cond_wait(&event->cond, &event->mutex);
  } else {
    struct timeval now;
    struct timespec abstime;
    long rel_secs = timeout_millis / 1000;
    long rel_millis = timeout_millis % 1000;
    long rel_nanos = rel_millis * 1000000;

    /* 1. use $now to get the absolute time
    ** 2. transfer the values from $now to $abstime
    ** 3. add the relative timeout to $abstime
    ** 4. call pthread_cond_timedwait, passing $abstime
    */
    /* 1: */
    gettimeofday(&now, NULL);
    /* 2: */
    abstime.tv_sec = now.tv_sec;
    abstime.tv_nsec = now.tv_usec * 1000;
    /* 3: */
    abstime.tv_sec += rel_secs;
    {
      long total_nanos = abstime.tv_nsec + rel_nanos;
      abstime.tv_sec += total_nanos / 1000000000;
      abstime.tv_nsec = total_nanos % 1000000000;
    }
    /* 4: */
    wait_result = pthread_cond_timedwait(&event->cond, &event->mutex, &abstime);
  }

  if ( pthread_mutex_unlock(&event->mutex) != 0 ) {
    return EVENT_ERROR;
  }

  if (wait_result == ETIMEDOUT) {
    return EVENT_TIMEOUT;
  } else if (wait_result == 0) {
    return EVENT_OK;
  } else {
    return EVENT_ERROR;
  }
} /* event_queue_wait */


int event_queue_signal(EventQueue *queue) {
  PlatformEventType event = queue->event;
  int signal_result;

  if ( pthread_mutex_lock(&event->mutex) != 0 ) {
    return -1;
  }

  signal_result = pthread_cond_signal(&event->cond);

  /* Notice the side-effective call to release the mutex in the conditional: */
  if ( pthread_mutex_unlock(&event->mutex) != 0 || signal_result != 0 ) {
    return -1;
  }

  return 0;
} /* event_queue_signal */


int event_queue_unsignal(EventQueue *queue) {
  /* Do nothing; this implementation uses automatically reset synch objects. */
  return 0;
} /* event_queue_unsignal */

/************************* PUBLIC FUNCTIONS:END ****************************/