diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/libcoopgamma.py | 29 | ||||
-rw-r--r-- | src/libcoopgamma_native.pyx.gpp | 92 |
2 files changed, 116 insertions, 5 deletions
diff --git a/src/libcoopgamma.py b/src/libcoopgamma.py index 31f5aaa..9aae31b 100644 --- a/src/libcoopgamma.py +++ b/src/libcoopgamma.py @@ -596,7 +596,14 @@ class Context: @param method:int|str? The adjustment method, `None` for automatic @param site:str? The site, `None` for automatic ''' - pass + if method is not None and isinstance(method, int): + method = str(method) + error = libcoopgamma_native_connect(method, site, self.address) + if error is not None: + if errno == 0: + pass # TODO server failed to initialise + else: + pass # TODO def detach(self): ''' @@ -625,7 +632,9 @@ class Context: @param nonblocking:bool Nonblocking mode? ''' - pass + error = libcoopgamma_native.libcoopgamma_native_set_nonblocking(self.address, nonbreaking) + if error != 0: + pass # TODO def flush(self): ''' @@ -635,7 +644,9 @@ class Context: with EINTR, call this function to complete the transfer. The `async` parameter will always be in a properly configured state if a function fails with EINTR. ''' - pass + error = libcoopgamma_native.libcoopgamma_native_flush(self.address) + if error != 0: + pass # TODO def synchronise(self, pending : list) -> int: ''' @@ -651,13 +662,21 @@ class Context: `None` if the message is ignored, which happens if corresponding AsyncContext is not listed. ''' - pass + pending = [p.address for p in pending] + (successful, value) = libcoopgamma_native.libcoopgamma_native_flush(self.address, pending) + if not successful: + if error == 0: + return None + else: + pass # TODO + else: + return value def skip_message(self): ''' Tell the library that you will not be parsing a receive message ''' - pass + libcoopgamma_native.libcoopgamma_native_skip_message(self.address) def get_crtcs_send(self) -> AsyncContext: ''' diff --git a/src/libcoopgamma_native.pyx.gpp b/src/libcoopgamma_native.pyx.gpp index 73d8353..b28c57b 100644 --- a/src/libcoopgamma_native.pyx.gpp +++ b/src/libcoopgamma_native.pyx.gpp @@ -1043,3 +1043,95 @@ def libcoopgamma_native_async_context_unmarshal(buf : bytes): ret0 = <int>libcoopgamma_async_context_unmarshal(this, <bytes>buf, &ret1) return (ret0, <int>ret1) + +def libcoopgamma_native_connect(method : str, site : str, address : int): + ''' + Connect to a coopgamma server, and start it if necessary + + Use `libcoopgamma_context_destroy` to disconnect + + SIGCHLD must not be ignored or blocked + + @param method:str? The adjustment method, `NULL` for automatic + @param site:str? The site, `NULL` for automatic + @param address:int The address of the state of the library, must be initialised + @return :int? `None`, 0 if the server on could not be initialised, + the value `errno` on other errors + ''' + cdef libcoopgamma_context_t* ctx = <libcoopgamma_context_t*><void*><intptr_t>address + if libcoopgamma_connect(method, site, ctx) < 0: + return int(errno) + return None + + +def libcoopgamma_native_set_nonblocking(address : int, nonblocking : bool): + ''' + By default communication is blocking, this function + can be used to switch between blocking and nonblocking + + After setting the communication to nonblocking, + `libcoopgamma_flush`, `libcoopgamma_synchronise` and + and request-sending functions can fail with EAGAIN and + EWOULDBLOCK. It is safe to continue with `libcoopgamma_flush` + (for `libcoopgamma_flush` it selfand equest-sending functions) + or `libcoopgamma_synchronise` just like EINTR failure. + + @param address:int The address of the state of the library, must be connected + @param nonblocking:bool Nonblocking mode? + @return :int Zero on success, the value of `errno` on error + ''' + cdef libcoopgamma_context_t* ctx = <libcoopgamma_context_t*><void*><intptr_t>address + if libcoopgamma_set_nonblocking(ctx, <int>(1 if nonblocking else 0)) < 0: + return int(errno) + return 0 + + +def libcoopgamma_native_flush(address : int): + ''' + Send all pending outbound data + + If this function or another function that sends a request + to the server fails with EINTR, call this function to + complete the transfer. The `async` parameter will always + be in a properly configured state if a function fails + with EINTR. + + @param address:int The address of the state of the library, must be connected + @return :int Zero on success, the value of `errno` on error + ''' + cdef libcoopgamma_context_t* ctx = <libcoopgamma_context_t*><void*><intptr_t>address + if libcoopgamma_flush(ctx) < 0: + return int(errno) + return 0 + + +def libcoopgamma_native_synchronise(address : int, pending : list): + ''' + Wait for the next message to be received + + @param address:int The address of the state of the library, must be connected + @param pending:list<int> Addresses of the information for each pending request + @return :(:bool, :int) If [0] = 0: [1] is the value of `errno` + [0] = 1: [1] is the selected request + ''' + cdef libcoopgamma_context_t* ctx = <libcoopgamma_context_t*><void*><intptr_t>address + cdef libcoopgamma_async_context_t* pends + cdef size_t selected = 0 + pends = <libcoopgamma_async_context_t*>malloc(n * sizeof(*pends)) + if pends is None: + pass + for i in range(len(pending)): + pends[i] = *<libcoopgamma_async_context_t*><void*><intptr_t>pendings[i] + if libcoopgamma_synchronise(ctx, pends, <size_t>len(pending), &selected) < 0: + return (False, int(errno)) + return (True, <int>selected) + + +def libcoopgamma_native_skip_message(address : int): + ''' + Tell the library that you will not be parsing a receive message + + @param address:int The address of the state of the library, must be connected + ''' + libcoopgamma_skip_message(<libcoopgamma_context_t*><void*><intptr_t>address) + |