--!A cross-platform build utility based on Lua -- -- Licensed under the Apache License, Version 2.0 (the "License"); -- you may not use this file except in compliance with the License. -- You may obtain a copy of the License at -- -- http://www.apache.org/licenses/LICENSE-2.0 -- -- Unless required by applicable law or agreed to in writing, software -- distributed under the License is distributed on an "AS IS" BASIS, -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -- See the License for the specific language governing permissions and -- limitations under the License. -- -- Copyright (C) 2015-present, Xmake Open Source Community. -- -- @author ruki -- @file pipe_event.lua -- -- define module local pipe_event = pipe_event or {} local _instance = _instance or {} -- load modules local pipe = require("base/pipe") local libc = require("base/libc") local bytes = require("base/bytes") local table = require("base/table") function _instance.new(name) local event = table.inherit(_instance) event._PIPE_EVENT = true event._BUFFER = bytes(2) event._NAME = name or "pipe_event" local reader, writer, errors = pipe.openpair("AA") if not reader or not writer then if reader then reader:close() end if writer then writer:close() end return nil, errors or "failed to open pipe" end event._READER = reader event._WRITER = writer event._WRITER_PTR = nil return event end function _instance:name() return self._NAME end function _instance:post() local writer = self._WRITER if not writer then return false, "pipe event writer closed" end local ok, errors = writer:write("1", {block = true}) if ok < 0 then return false, errors or "pipe event post failed" end writer:close() self._WRITER = nil self._WRITER_PTR = nil return true end function _instance:wait(timeout) if not self._READER then return false, "pipe event reader closed" end local read, read_errors = self._READER:read(self._BUFFER, 1, {block = true, timeout = timeout}) if read < 0 then return false, read_errors end return read end function _instance:close() if self._READER then self._READER:close() end if self._WRITER then self._WRITER:close() end self._READER = nil self._WRITER = nil self._WRITER_PTR = nil end -- return pipe cdata for serialization (writer pointer is stable for passing across threads) function _instance:cdata() if self._WRITER then return self._WRITER:cdata() end return self._WRITER_PTR end function _instance:__gc() self:close() end function _instance:_serialize() if not self._WRITER and self._WRITER_PTR then return {ptr = self._WRITER_PTR, name = self:name()} end if not self._WRITER then return nil end local ptr = libc.dataptr(self._WRITER:cdata(), {ffi = false}) if not ptr then return nil end self._WRITER._PIPE = nil self._WRITER = nil self._WRITER_PTR = ptr return {ptr = ptr, name = self:name()} end function _instance:_deserialize(data) if not data or not data.ptr then return false, "invalid pipe event data" end self:close() local writer = pipe.new(libc.ptraddr(data.ptr, {ffi = false})) if not writer then return false, "invalid pipe pointer" end self._NAME = data.name or self._NAME or "pipe_event" self._WRITER = writer self._WRITER_PTR = data.ptr return true end function pipe_event.new(name) return _instance.new(name) end return pipe_event