forked from rochus-keller/CspChan
-
Notifications
You must be signed in to change notification settings - Fork 0
/
CspChan.h
128 lines (108 loc) · 6.86 KB
/
CspChan.h
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
#ifndef CSP_CHANNEL_H
#define CSP_CHANNEL_H
/*
* Copyright 2023 Rochus Keller <mailto:[email protected]>
*
* This file may be used under the terms of the GNU Lesser
* General Public License version 2.1 or version 3 as published by the Free
* Software Foundation and appearing in the file LICENSE.LGPLv21 and
* LICENSE.LGPLv3 included in the packaging of this file. Please review the
* following information to ensure the GNU Lesser General Public License
* requirements will be met: https://www.gnu.org/licenses/lgpl.html and
* http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
*
* Alternatively this file may be used under the terms of the Mozilla
* Public License. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
/* CspChan:
* This is a C89 library which implements CSP channels in a similar way as e.g. in the Go programmin language.
* The library uses pthreads (on Unix) or Win32 threads (on Windows). Thus the practical number
* of available threads is much lower than in languages like Go, Joyce or SuperPascal. But the semantics
* of the channels otherwise corresponds pretty well to the mentioned languages, including the either
* blocking or non-blocking select. A future version of the library might support thread pools or even
* something like Go routines (with user-mode scheduling in addition to threads). */
#ifdef __cplusplus
extern "C" {
#endif
#ifdef _WIN32
/* comment the following #define if you statically link the library. */
#define CSPCHANEXP __declspec(dllexport)
#else
#define CSPCHANEXP
#endif
/* Main API */
typedef struct CspChan_t CspChan_t;
/* CspChan_create:
* Create a channel suited to transport messages of msgLen bytes. The channel blocks on send
* (if buffer is full) and receive (if buffer is empty). As in Go the capacity of the channel can
* be set using the queueLen parameter. Set queueLen to 0 for an unbuffered channel (which is
* not the same as a channel with queueLen 1). An unbuffered channel blocks until a rendezvous
* with the other thread has occurred (i.e. a reader with a writer thread or vize versa).
* As soon as created, a channel can be used for communication until it is closed or disposed.
* Channels are thread-safe and thus can safely be passed to and used by other threads in parallel. */
CSPCHANEXP CspChan_t* CspChan_create(unsigned short queueLen, unsigned short msgLen );
/* CspChan_close:
* The call to CspChan_close is optional; it is useful to signal to a thread that it should stop
* running without an extra channel. It is legal though to directly call CspChan_dispose when
* the channel is no longer used. This procedure also signals all threads waiting on this channel. */
CSPCHANEXP void CspChan_close(CspChan_t*);
/* CspChan_closed:
* Returns the closed status of the channel. As soon as CspChan_close was called, this function
* returns 1, otherwise 0. */
CSPCHANEXP int CspChan_closed(CspChan_t*);
/* CspChan_dispose:
* Delete a channel which was created by CspChan_create earlier. This procedure also signals all threads
* waiting on this channel. After the call the channel pointer is invalid. */
CSPCHANEXP void CspChan_dispose(CspChan_t*);
/* CspChan_send:
* Send a message of msgLen bytes (see CspChan_create) over the channel. If the channel is full or
* unbuffered (see CspChan_create), the calling thread blocks, thus waiting for a rendezvous with a thread
* calling CspChan_receive on the same channel. If the channel was closed, the call immediately returns
* with no effect. The parameter dataPtr is the address of the variable the data of which are sent. */
CSPCHANEXP void CspChan_send(CspChan_t*, void* dataPtr);
/* CspChan_receive:
* Receive a message of msgLen bytes (see CspChan_create) from the channel. If the channel is empty or
* unbuffered (see CspChan_create), the calling thread blocks, thus waiting for a rendezvous with a thread
* calling CspChan_send on the same channel. If the channel was closed, the call immediately returns
* with no effect. The parameter dataPtr is the address of the variable which receives the data. */
CSPCHANEXP void CspChan_receive(CspChan_t*, void* dataPtr);
/* CspChan_select:
* This function works like the select statement (without default) of the Go programming language.
* It accepts an array of receiver channels and receiver variable addresses of length rCount and an
* array of sender channels and sender variable addresses of length sCount. If rCount is 0, receiver
* and rData can be NULL; if sCount is 0, sender and sData can be NULL.
* When called, CspChan_select checks which receivers and senders are ready for communication, and
* randomly (using the C rand() function) selects one and calls CspChan_send/receive on it. If none
* of the channels is ready for communication, the call blocks until any of the channels is ready, and
* then calls CspChan_send/receive on it. The function returns the index of the selected channel or -1;
* the index assumes a combined receiver|sender array, i.e. an index >= rCount applies to the sender array.
* Closed channels are ignored by this function. */
CSPCHANEXP int CspChan_select(CspChan_t** receiver, void** rData, unsigned int rCount,
CspChan_t** sender, void** sData, unsigned int sCount );
/* CspChan_nb_select:
* This function works like the select statement (with default) of the Go programming language.
* It accepts an array of receiver channels and receiver variable addresses of length rCount and an
* array of sender channels and sender variable addresses of length sCount. If rCount is 0, receiver
* and rData can be NULL; if sCount is 0, sender and sData can be NULL.
* When called, CspChan_nb_select checks which receivers and senders are ready for communication, and
* randomly (using the C rand() function) selects one and calls CspChan_send/receive on it. If none
* of the channels is ready for communication, the call immediately returns with -1.
* The function otherwise returns the index of the selected channel; the index assumes a combined
* receiver|sender array, i.e. an index >= rCount applies to the sender array.
* Closed channels are ignored by this function. */
CSPCHANEXP int CspChan_nb_select(CspChan_t** receiver, void** rData, unsigned int rCount,
CspChan_t** sender, void** sData, unsigned int sCount );
/* Helper API for applications which don't want to directly deal with a thread API. */
/* CspChan_fork:
* Create a new thread (or possibly re-use one from the pool) and use it to run the agent function.
* If the thread could not be started (possibly because no more threads are available) the function
* returns 0, otherwise it returns 1. */
CSPCHANEXP int CspChan_fork(void* (*agent)(void*), void * arg);
/* CspChan_sleep:
* Suspends the calling thread for the given number of milliseconds. */
CSPCHANEXP void CspChan_sleep(unsigned int milliseconds);
#ifdef __cplusplus
}
#endif
#endif /* CSP_CHANNEL_H */