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
|
--!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
|