def _on_tick_(timer): ec = core.get_ec() self = ec.handles.get(timer, Timer) try: Event_dispatch(self.on_tick, []) except Unwinder as unwinder: core.root_unwind(ec, unwinder)
def write_message(self, std, text): if core.get_ec() != self.ec: # Just discard those damn messages if return # they come up in wrong thread. array = space.to_uint8array(text) bufs, nbufs = uv_callback.obj2bufs(array) if isinstance(std, fs.WriteStream) and not std.fileobj.closed: fd = std.fileobj.fd req = lltype.malloc(uv.fs_ptr.TO, flavor='raw', zero=True) _ = uv.fs_write(self.ec.uv_loop, req, fd, bufs, nbufs, std.offset, lltype.nullptr(uv.fs_cb.TO)) if rffi.r_long(req.c_result) > 0: std.offset += rffi.r_long(req.c_result) lltype.free(bufs, flavor="raw") lltype.free(req, flavor="raw") elif isinstance(std, uv_stream.Stream) and not std.closed: stream = std.stream req = lltype.malloc(uv.write_ptr.TO, flavor='raw', zero=True) req.c_data = rffi.cast(rffi.VOIDP, bufs) res = uv.write(req, stream, bufs, nbufs, _logging_write_callback_) if rffi.r_long(res) < 0: lltype.free(bufs, flavor="raw") lltype.free(req, flavor="raw") else: return
def UDP_recv(self): self.check_closed() ec = core.get_ec() if len(self.read_queue) == 0: uv_callback.push(ec.uv__udp_recv, self) status = uv.udp_recv_start(self.udp, _udp_alloc_callback_, _udp_read_callback_once_) if status < 0: uv_callback.drop(ec.uv__udp_recv, self.udp) raise uv_callback.to_error(status) if len(self.read_queue) == 0: if self.read_greenlet is not None: raise unwind(LError(u"async collision")) self.read_greenlet = ec.current core.switch([ec.eventloop]) array, nread, status, addr, flags = self.read_queue.pop(0) if nread < 0: raise uv_callback.to_error(nread) if status < 0: raise uv_callback.to_error(status) if array is None: array = Uint8Slice(lltype.nullptr(rffi.UCHARP.TO), 0, None) elif array.length != nread: array = array.subslice(nread) res = Exnihilo() res.setattr(u"data", array) res.setattr(u"addr", addr) res.setattr(u"flags", Integer(rffi.r_long(flags))) return res
def __init__(self, handle): self.ec = core.get_ec() self.handle = handle self.greenlet = None self.pending = True self.data = blank_data push_handle(getattr(self.ec, uv_name), handle, self)
def Stream_read(self): self.check_closed() ec = core.get_ec() if len(self.read_queue) == 0: uv_callback.push(ec.uv__read, self) status = uv.read_start(self.stream, _alloc_callback_, _read_callback_once_) if status < 0: uv_callback.drop(ec.uv__read, self.stream) raise uv_callback.to_error(status) if len(self.read_queue) == 0: if self.read_greenlet is not None: raise unwind(LError(u"async collision")) self.read_greenlet = ec.current core.switch([ec.eventloop]) array, nread, status = self.read_queue.pop(0) if nread < 0: raise uv_callback.to_error(nread) if status < 0: raise uv_callback.to_error(status) if array is None: return Uint8Slice(lltype.nullptr(rffi.UCHARP.TO), 0, None) if array.length == nread: return array return array.subslice(nread)
def wakeup_sleeper(handle): ec = core.get_ec() task = ec.uv_sleepers.pop(rffi.cast_ptr_to_adr(handle)) ec.enqueue(task) uv.timer_stop(handle) uv.close(rffi.cast(uv.handle_ptr, handle), uv.free)
def sleep_callback(duration, func): ec = core.get_ec() uv_sleeper = uv.malloc_bytes(uv.timer_ptr, uv.handle_size(uv.TIMER)) ec.uv_sleepers[rffi.cast_ptr_to_adr(uv_sleeper)] = core.to_greenlet([func]) uv.timer_init(ec.uv_loop, uv_sleeper) uv.timer_start(uv_sleeper, wakeup_sleeper, int(duration.number * 1000), 0) return space.null
def TCP_init(): ec = core.get_ec() tcp = lltype.malloc(uv.tcp_ptr.TO, flavor="raw", zero=True) status = uv.tcp_init(ec.uv_loop, tcp) if status < 0: lltype.free(tcp, flavor="raw") raise uv_callback.to_error(status) return TCP(tcp)
def Handle2_close(self): self.check_closed() ec = core.get_ec() if uv.is_closing(self.handle) == 0: uv.close(self.handle, _on_close_) # The call of _on_close_ is always deferred # to the next round of the event loop. return Event_wait(self.on_close)
def _callback_(handle, *data): ec = core.get_ec() resp = pop_handle(getattr(ec, uv_name), handle) if len(data) > 0: resp.data = data resp.pending = False if resp.greenlet is not None: core.root_switch(ec, [resp.greenlet])
def UDP_init(): ec = core.get_ec() udp = lltype.malloc(uv.udp_ptr.TO, flavor="raw", zero=True) status = uv.udp_init(ec.uv_loop, udp) if status < 0: lltype.free(udp, flavor="raw") raise uv_callback.to_error(status) return UDP(udp)
def alloc_pipe(ipc): ec = core.get_ec() pipe = lltype.malloc(uv.pipe_ptr.TO, flavor="raw", zero=True) status = uv.pipe_init(ec.uv_loop, pipe, ipc) if status < 0: lltype.free(pipe, flavor='raw') raise uv_callback.to_error(status) return Pipe(pipe)
def _udp_alloc_callback_(handle, suggested_size, buf): ec = core.get_ec() self = uv_callback.peek(ec.uv__udp_recv, handle) if self.read_buffer_size > 0: array = alloc_uint8array(self.read_buffer_size) else: array = alloc_uint8array(rffi.r_long(suggested_size)) self.alloc_buffers.append(array) buf.c_base = rffi.cast(rffi.CCHARP, array.uint8data) buf.c_len = rffi.r_size_t(array.length)
def _on_close_(handle): ec = core.get_ec() self = ec.handles.free(handle) self.closed = True try: Event_dispatch(self.on_close, []) for event in self.events: Event_close(event) except Unwinder as unwinder: core.root_unwind(unwinder)
def Watch_wait(self): if len(self.data) > 0: return self.data.pop(0) elif self.status < 0: raise uv_callback.to_error(self.status) else: if self.greenlet is not None: raise unwind(LError(u"fs.watch retrieval collision")) ec = core.get_ec() self.greenlet = ec.current return core.switch([ec.eventloop])
def Stream_listen(self, backlog): self.check_closed() ec = core.get_ec() uv_callback.push(ec.uv__connection, self) status = uv.listen(self.stream, backlog.value, _listen_callback_) if status < 0: uv_callback.drop(ec.uv__connection, self.stream) raise uv_callback.to_error(status) else: self.listening = True return null
def _listen_callback_(handle, status): status = int(status) ec = core.get_ec() if status < 0: self = uv_callback.drop(ec.uv__connection, handle) self.listen_status = status else: self = uv_callback.peek(ec.uv__connection, handle) self.listen_count += 1 if self.accept_greenlet is not None: greenlet, self.accept_greenlet = self.accept_greenlet, None core.root_switch(ec, [greenlet])
def sleep_greenlet(duration): ec = core.get_ec() if ec.current == ec.eventloop: raise space.OldError(u"bad context for greenlet sleep") assert ec.current.is_exhausted() == False uv_sleeper = uv.malloc_bytes(uv.timer_ptr, uv.handle_size(uv.TIMER)) ec.uv_sleepers[rffi.cast_ptr_to_adr(uv_sleeper)] = ec.current uv.timer_init(ec.uv_loop, uv_sleeper) uv.timer_start(uv_sleeper, wakeup_sleeper, int(duration.number * 1000), 0) return core.switch([ec.eventloop])
def Stream_accept(self): self.check_closed() if self.listen_count > 0: if self.accept_greenlet is not None: raise unwind(LError(u"async collision")) ec = core.get_ec() self.accept_greenlet = ec.current core.switch([ec.eventloop]) check(self.listen_status) self.listen_count -= 1 client = self.new_stream() check(uv.accept(self.stream, client.stream)) return client
def _read_callback_once_(stream, nread, buf): ec = core.get_ec() self = uv_callback.drop(ec.uv__read, stream) for array in self.alloc_buffers: if rffi.cast(rffi.CCHARP, array.uint8data) == buf.c_base: break else: array = None status = uv.read_stop(stream) self.read_queue.append((array, nread, status)) if self.read_greenlet is not None: greenlet, self.read_greenlet = self.read_greenlet, None core.root_switch(ec, [greenlet])
def normal_startup(argv): if len(argv) > 0: main_script = argv[0] else: main_script = pathobj.concat(core.get_ec().lever_path, pathobj.parse(u"app/main.lc")) main_script = space.String(pathobj.os_stringify(main_script)) module = module_resolution.start(main_script) try: main_func = module.getattr(u"main") except space.Unwinder as unwinder: pass # in this case main_func just isn't in the module. else: main_func.call([space.List(argv)]) return space.null
def start(main_script): assert isinstance(main_script, String) lib_scope = ModuleScope( pathobj.concat(core.get_ec().lever_path, pathobj.parse(u"lib")), root_module) attach_compiler(lib_scope) main_path = pathobj.os_parse(resuffix(main_script.string, u".lc", u"")) mi = moduleinfo(pathobj.abspath(main_path)) scope = ModuleScope(mi.directory, lib_scope) this = Module(mi.name.string, {}, extends=base.module) # base.module if not (mi.lc_present or mi.cb_present): raise OldError(u"main module not present") scope.setcache(main_path, this, max(mi.lc_mtime, mi.cb_mtime)) mi.default_config(this, scope) mi.loadit(this, scope) return this
def Watch_init(path): ec = core.get_ec() path = pathobj.os_stringify(path).encode('utf-8') handle = lltype.malloc(uv.fs_event_ptr.TO, flavor='raw', zero=True) res = uv.fs_event_init(ec.uv_loop, handle) if res < 0: lltype.free(handle, flavor='raw') raise uv_callback.to_error(res) self = Watch(handle) uv_callback.push(ec.uv__fs_event, self) res = uv.fs_event_start(self.fs_event, _fs_event_cb_, path, 0) if res < 0: uv_callback.drop(ec.uv__fs_event, self.fs_event) Handle_close(self) raise uv_callback.to_error(res) return self
def _udp_read_callback_once_(stream, nread, buf, addr, flags): ec = core.get_ec() self = uv_callback.drop(ec.uv__udp_recv, stream) for array in self.alloc_buffers: if rffi.cast(rffi.CCHARP, array.uint8data) == buf.c_base: break else: array = None status = uv.udp_recv_stop(stream) if addr: addr = copy_to_uint8array(rffi.cast(rffi.VOIDP, addr), rffi.sizeof(uv.sockaddr_storage), rffi.sizeof(uv.sockaddr_storage)) else: addr = null self.read_queue.append((array, nread, status, addr, flags)) if self.read_greenlet is not None: greenlet, self.read_greenlet = self.read_greenlet, None core.root_switch(ec, [greenlet])
def invoke_callback(ffi_cif, ll_res, ll_args, ll_userdata): """ Callback specification. ffi_cif - something ffi specific, don't care ll_args - rffi.VOIDPP - pointer to array of pointers to args ll_res - rffi.VOIDP - pointer to result ll_userdata - a special structure which holds necessary information (what the real callback is for example), casted to VOIDP """ # Reveal the callback. addr = rffi.cast(llmemory.Address, ll_userdata) gcref = rgc.reveal_gcref(addr) callback = rgc.try_cast_gcref_to_instance(Callback, gcref) if callback is None: try: os.write(STDERR, "Critical error: invoking a callback that was already freed\n") except: pass # We cannot do anything here. else: #must_leave = False try: # must_leave = space.threadlocals.try_enter_thread(space) # Should check for separate threads here and crash # if the callback comes from a thread that has no execution context. cfunc = callback.cfunc argv = [] for i in range(0, len(cfunc.argtypes)): argv.append( cfunc.argtypes[i].load(ll_args[i], False) ) value = callback.callback.call(argv) if isinstance(cfunc.restype, Type): cfunc.restype.store(None, ll_res, value) except Unwinder as unwinder: core.root_unwind(core.get_ec(), unwinder) except Exception as e: try: os.write(STDERR, "SystemError: callback raised ") os.write(STDERR, str(e)) os.write(STDERR, "\n") except: pass
def _fs_event_cb_(handle, filename, events, status): ec = core.get_ec() try: self = uv_callback.peek(ec.uv__fs_event, handle) status = rffi.r_long(status) if self.status == 0 and status < 0: uv_callback.drop(ec.uv__fs_event, handle) self.status = status return obj = Exnihilo() obj.setattr(u"path", from_cstring(rffi.charp2str(filename))) if rffi.r_long(events) == 1: obj.setattr(u"type", String(u"rename")) else: obj.setattr(u"type", String(u"change")) if self.greenlet is None: self.data.append(obj) else: greenlet, self.greenlet = self.greenlet, None core.switch([greenlet, obj]) except Unwinder as unwinder: core.root_unwind(ec, unwinder)
def exit(obj): ec = core.get_ec() ec.exit_status = 0 if obj is None else int(obj.value) uv.stop(ec.uv_loop) ec.enqueue(ec.current) # Trick to ensure we get Discard -exception here return core.switch([ec.eventloop]) # Once they are created.
def getcurrent(): return core.get_ec().current
def get_sthread(): ec = core.get_ec() if not ec.sthread: ec.sthread = SThread(ec.config) return ec.sthread
def __init__(self, handle): self.handle = handle self.closed = False self.on_close = Event() self.events = [self.on_close] core.get_ec().handles.stash(self.handle, self)