diff --git a/Makefile b/Makefile
index bbb7277..7c0b584 100644
--- a/Makefile
+++ b/Makefile
@@ -50,13 +50,13 @@ test: certs
$(LUA) $(DELIM) $(PKGPATH) tests/largetransfer.lua
$(LUA) $(DELIM) $(PKGPATH) tests/lock.lua
$(LUA) $(DELIM) $(PKGPATH) tests/loop_starter.lua
+ $(LUA) $(DELIM) $(PKGPATH) tests/pause.lua
$(LUA) $(DELIM) $(PKGPATH) tests/queue.lua
$(LUA) $(DELIM) $(PKGPATH) tests/removeserver.lua
$(LUA) $(DELIM) $(PKGPATH) tests/removethread.lua
$(LUA) $(DELIM) $(PKGPATH) tests/request.lua 'http://www.google.com'
$(LUA) $(DELIM) $(PKGPATH) tests/request.lua 'https://www.google.nl' true
$(LUA) $(DELIM) $(PKGPATH) tests/semaphore.lua
- $(LUA) $(DELIM) $(PKGPATH) tests/sleep.lua
$(LUA) $(DELIM) $(PKGPATH) tests/starve.lua
$(LUA) $(DELIM) $(PKGPATH) tests/tcptimeout.lua
$(LUA) $(DELIM) $(PKGPATH) tests/timer.lua
diff --git a/docs/index.html b/docs/index.html
index 092dbaa..d5fd87a 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -105,6 +105,8 @@
History
Fix: an error in the timer callback would kill the timer.
Added: copas.geterrorhandler
to retrieve the active errorhandler.
Added: option errorhandler
for timer objects.
+ Added: copas.pause
and copas.pauseforever
to replace copas.sleep
. The latter
+ method can accidentally sleep-forever if time arithmetic returns a negative result.
Change: renamed copas.setErrorHandler
to copas.seterrorhandler
.
Change: renamed copas.useSocketTimeoutErrors
to copas.usesockettimeouterrors
.
diff --git a/docs/manual.html b/docs/manual.html
index 9cd1c51..76f28a7 100644
--- a/docs/manual.html
+++ b/docs/manual.html
@@ -381,7 +381,7 @@ Synchronization primitives
end
print("doing something on my own")
- copas.sleep() -- allow to yield, while inside the lock
+ copas.pause() -- allow to yield, while inside the lock
print("after " .. ok .. " seconds waiting")
lock:release()
diff --git a/docs/reference.html b/docs/reference.html
index 7176151..d31e35c 100644
--- a/docs/reference.html
+++ b/docs/reference.html
@@ -298,14 +298,23 @@ Non-blocking data exchange and timer/sleep functions
exchange data with other services.
+ copas.pause([delay])
+ - Pauses the current co-routine. Parameter
delay
(in seconds) is optional
+ and defaults to 0. If delay <= 0
then it will pause for 0 seconds.
+
+
+ copas.pauseforever()
+ - Pauses the current co-routine until explicitly woken by a call to
+
copas.wakeup()
.
+
+
copas.sleep([sleeptime])
- - Pauses the current co-routine. Parameter
sleeptime
(in seconds) is optional
- and defaults to 0. If sleeptime < 0
- then it will sleep until explicitly woken by a call to copas.wakeup()
.
+ - Deprecated: use
copas.pause
and copas.pauseforever
+ instead.
copas.wakeup(co)
- co
is the coroutine to wakeup, see copas.sleep()
.
+ co
is the coroutine to wakeup, see copas.pauseforever()
.
sock:close()
diff --git a/src/copas.lua b/src/copas.lua
index ced7c1d..24f2b67 100644
--- a/src/copas.lua
+++ b/src/copas.lua
@@ -497,7 +497,7 @@ function copas.receive(client, pattern, part)
-- guarantees that high throughput doesn't take other threads to starvation
if (math.random(100) > 90) then
- copas.sleep(0)
+ copas.pause()
end
if s then
@@ -541,7 +541,7 @@ function copas.receivefrom(client, size)
-- garantees that high throughput doesn't take other threads to starvation
if (math.random(100) > 90) then
- copas.sleep(0)
+ copas.pause()
end
if s then
@@ -578,7 +578,7 @@ function copas.receivepartial(client, pattern, part)
-- guarantees that high throughput doesn't take other threads to starvation
if (math.random(100) > 90) then
- copas.sleep(0)
+ copas.pause()
end
if s or (type(part) == "string" and #part > orig_size) then
@@ -626,7 +626,7 @@ function copas.send(client, data, from, to)
-- guarantees that high throughput doesn't take other threads to starvation
if (math.random(100) > 90) then
- copas.sleep(0)
+ copas.pause()
end
if s then
@@ -1198,7 +1198,7 @@ function copas.addnamedthread(name, handler, ...)
-- create a coroutine that skips the first argument, which is always the socket
-- passed by the scheduler, but `nil` in case of a task/thread
local thread = coroutine_create(function(_, ...)
- copas.sleep(0)
+ copas.pause()
return handler(...)
end)
if name then
@@ -1230,10 +1230,29 @@ end
-- yields the current coroutine and wakes it after 'sleeptime' seconds.
-- If sleeptime < 0 then it sleeps until explicitly woken up using 'wakeup'
+-- TODO: deprecated, remove in next major
function copas.sleep(sleeptime)
coroutine_yield((sleeptime or 0), _sleeping)
end
+
+-- yields the current coroutine and wakes it after 'sleeptime' seconds.
+-- if sleeptime < 0 then it sleeps 0 seconds.
+function copas.pause(sleeptime)
+ if sleeptime and sleeptime > 0 then
+ coroutine_yield(sleeptime, _sleeping)
+ else
+ coroutine_yield(0, _sleeping)
+ end
+end
+
+
+-- yields the current coroutine until explicitly woken up using 'wakeup'
+function copas.pauseforever()
+ coroutine_yield(-1, _sleeping)
+end
+
+
-- Wakes up a sleeping coroutine 'co'.
function copas.wakeup(co)
_sleeping:wakeup(co)
@@ -1258,7 +1277,7 @@ do
time_out_thread = copas.addnamedthread("copas_core_timer", function()
while true do
- copas.sleep(TIMEOUT_PRECISION)
+ copas.pause(TIMEOUT_PRECISION)
timerwheel:step()
end
end)
@@ -1358,7 +1377,7 @@ local _sleeping_task = {} do
local co = _sleeping:pop(now)
while co do
-- we're pushing them to _resumable, since that list will be replaced before
- -- executing. This prevents tasks running twice in a row with sleep(0) for example.
+ -- executing. This prevents tasks running twice in a row with pause(0) for example.
-- So here we won't execute, but at _resumable step which is next
_resumable:push(co)
co = _sleeping:pop(now)
diff --git a/src/copas/lock.lua b/src/copas/lock.lua
index b16a03d..3a8dadd 100644
--- a/src/copas/lock.lua
+++ b/src/copas/lock.lua
@@ -124,7 +124,7 @@ function lock:get(timeout)
copas.timeout(timeout, timeout_handler)
start_time = gettime()
- copas.sleep(-1)
+ copas.pauseforever()
local err = self.errors[co]
self.errors[co] = nil
diff --git a/src/copas/semaphore.lua b/src/copas/semaphore.lua
index f88d3d0..db7eaa3 100644
--- a/src/copas/semaphore.lua
+++ b/src/copas/semaphore.lua
@@ -160,7 +160,7 @@ function semaphore:take(requested, timeout)
}
self.q_tail = self.q_tail + 1
- copas.sleep(-1) -- block until woken
+ copas.pauseforever() -- block until woken
if self.to_flags[co] then
-- a timeout happened
self.to_flags[co] = nil
diff --git a/src/copas/timer.lua b/src/copas/timer.lua
index 91c5b84..ba96711 100644
--- a/src/copas/timer.lua
+++ b/src/copas/timer.lua
@@ -28,7 +28,7 @@ do
if self.errorhandler then
copas.seterrorhandler(self.errorhandler)
end
- copas.sleep(initial_delay)
+ copas.pause(initial_delay)
while true do
if not self.cancelled then
if not self.recurring then
@@ -52,7 +52,7 @@ do
return
end
- copas.sleep(self.delay)
+ copas.pause(self.delay)
end
end
diff --git a/tests/close.lua b/tests/close.lua
index c26d406..cbc31b3 100644
--- a/tests/close.lua
+++ b/tests/close.lua
@@ -34,13 +34,13 @@ copas.loop(function()
copas.addserver(server, copas.handler(function(conn_skt)
-- client connected, we're not doing anything, let the client
-- wait in the read/write queues
- copas.sleep(2)
+ copas.pause(2)
-- now we're closing the connecting_socket
close_time = socket.gettime()
print("closing client socket now, client receive and send operation should immediately error out now")
client_socket:close()
- copas.sleep(10)
+ copas.pause(10)
conn_skt:close()
copas.removeserver(server)
print "timeout, test failed"
diff --git a/tests/errhandlers.lua b/tests/errhandlers.lua
index 25755d0..cc5de10 100644
--- a/tests/errhandlers.lua
+++ b/tests/errhandlers.lua
@@ -63,7 +63,7 @@ if _VERSION ~= "Lua 5.1" then
end
f()
end)
- copas.sleep(1)
+ copas.pause(1)
end)
print = old_print --luacheck: ignore
@@ -83,7 +83,7 @@ tests.yielding_from_user_code_fails = function()
end
copas.loop(function()
- copas.sleep(1)
+ copas.pause(1)
coroutine.yield() -- directly yield to Copas
end)
@@ -137,7 +137,7 @@ tests.timerwheel_callbacks_call_the_default_error_handler = function()
copas.setErrorHandler(function() call_count = call_count - 10 end, true)
copas.loop(function()
copas.timeout(0.01, function(co) error("hi there!") end)
- copas.sleep(1)
+ copas.pause(1)
end)
assert(call_count == -10, "expected callcount -10, got: " .. tostring(call_count))
diff --git a/tests/exit.lua b/tests/exit.lua
index 53ed54e..ecf7321 100644
--- a/tests/exit.lua
+++ b/tests/exit.lua
@@ -7,7 +7,7 @@ local done = false
copas.addthread(function()
for i = 1, 5 do
- copas.sleep(0)
+ copas.pause()
print(i)
end
@@ -43,7 +43,7 @@ copas.addserver(server, function(skt)
end)
copas.addthread(function()
- copas.sleep(1)
+ copas.pause(1)
local skt = socket.connect("localhost", 20000)
print("Sending "..message.."\\n")
local bytes = copas.send(skt, message.."\n")
diff --git a/tests/exittest.lua b/tests/exittest.lua
index 20ebae5..5d4ad67 100644
--- a/tests/exittest.lua
+++ b/tests/exittest.lua
@@ -19,8 +19,8 @@ print("1) success")
print("2) Testing exiting when a task finishes within the loop")
copas.addthread(function()
- copas.sleep(0.1) -- wait until loop is running
- copas.sleep(0.1) -- wait again to make sure its not the initial step in the loop
+ copas.pause(0.1) -- wait until loop is running
+ copas.pause(0.1) -- wait again to make sure its not the initial step in the loop
print("","2 running...")
testran = 2
end)
@@ -40,8 +40,8 @@ print("3) success")
print("4) Testing exiting when a task fails in the loop")
copas.addthread(function()
- copas.sleep(0.1) -- wait until loop is running
- copas.sleep(0.1) -- wait again to make sure its not the initial step in the loop
+ copas.pause(0.1) -- wait until loop is running
+ copas.pause(0.1) -- wait again to make sure its not the initial step in the loop
print("","4 running...")
testran = 4
error("error on purpose")
@@ -54,7 +54,7 @@ print("5) Testing exiting when a task permanently sleeps before the loop")
copas.addthread(function()
print("","5 running...")
testran = 5
- copas.sleep(-1) -- sleep until explicitly woken up
+ copas.pauseforever() -- sleep until explicitly woken up
end)
copas.loop()
assert(testran == 5, "Test 5 was not executed!")
@@ -62,11 +62,11 @@ print("5) success")
print("6) Testing exiting when a task permanently sleeps in the loop")
copas.addthread(function()
- copas.sleep(0.1) -- wait until loop is running
- copas.sleep(0.1) -- wait again to make sure its not the initial step in the loop
+ copas.pause(0.1) -- wait until loop is running
+ copas.pause(0.1) -- wait again to make sure its not the initial step in the loop
print("","6 running...")
testran = 6
- copas.sleep(-1) -- sleep until explicitly woken up
+ copas.pauseforever() -- sleep until explicitly woken up
end)
copas.loop()
assert(testran == 6, "Test 6 was not executed!")
diff --git a/tests/http-timeout.lua b/tests/http-timeout.lua
index ecfab48..48be63a 100644
--- a/tests/http-timeout.lua
+++ b/tests/http-timeout.lua
@@ -64,7 +64,7 @@ local function runtest()
os.exit(1)
end
-- we timeout on the request, so sleep here and exit
- copas.sleep(timeout + 1) -- sleep 1 second more than the requester timeout, to force a timeout on the request
+ copas.pause(timeout + 1) -- sleep 1 second more than the requester timeout, to force a timeout on the request
print("Server reading port 49500: request-timeout complete")
return skt:close()
end
@@ -105,7 +105,7 @@ local function runtest()
os.exit(1)
end
- copas.sleep(timeout + 1) -- sleep 1 second more than the requester timeout, to force a timeout on the response
+ copas.pause(timeout + 1) -- sleep 1 second more than the requester timeout, to force a timeout on the response
print("Server reading port 49500: response-timeout complete")
return skt:close()
end))
@@ -115,7 +115,7 @@ local function runtest()
copas.addnamedthread("test request", function()
print "Waiting a bit for server to start..."
- copas.sleep(1) -- give server some time to start
+ copas.pause(1) -- give server some time to start
do
print("first test: succesfull round trip")
@@ -152,7 +152,7 @@ local function runtest()
-- cleanup; sleep 2 secs to wait for closing server socket
-- to ensure any error messages do not get intermixed with the next tests output
- copas.sleep(2)
+ copas.pause(2)
print(("="):rep(80))
end
@@ -192,7 +192,7 @@ local function runtest()
-- cleanup; sleep 2 secs to wait for closing server socket
-- to ensure any error messages do not get intermixed with the next tests output
- copas.sleep(2)
+ copas.pause(2)
print(("="):rep(80))
end
@@ -232,7 +232,7 @@ local function runtest()
-- cleanup; sleep 2 secs to wait for closing server socket
-- to ensure any error messages do not get intermixed with the next tests output
- copas.sleep(2)
+ copas.pause(2)
print(("="):rep(80))
end
@@ -272,7 +272,7 @@ local function runtest()
-- cleanup; sleep 2 secs to wait for closing server socket
-- to ensure any error messages do not get intermixed with the next tests output
- copas.sleep(2)
+ copas.pause(2)
print(("="):rep(80))
end
@@ -312,7 +312,7 @@ local function runtest()
-- cleanup; sleep 2 secs to wait for closing server socket
-- to ensure any error messages do not get intermixed with the next tests output
- copas.sleep(2)
+ copas.pause(2)
print(("="):rep(80))
end
diff --git a/tests/largetransfer.lua b/tests/largetransfer.lua
index 02987e2..21045a9 100644
--- a/tests/largetransfer.lua
+++ b/tests/largetransfer.lua
@@ -76,7 +76,7 @@ local function runtest()
copas.addnamedthread("test timeout thread", function()
local i = 1
while done ~= 4 do
- copas.sleep(1)
+ copas.pause(1)
print(i, "seconds:", socket.gettime()-start)
i = i + 1
if i > 60 then
diff --git a/tests/lock.lua b/tests/lock.lua
index cd170c5..6e167cd 100644
--- a/tests/lock.lua
+++ b/tests/lock.lua
@@ -54,7 +54,7 @@ copas.loop(function()
--print(i, "got it!")
success_count = success_count + 1
if i == size/3 then
- copas.sleep(3) -- keep it long enough for the next 500 to timeout
+ copas.pause(3) -- keep it long enough for the next 500 to timeout
--print(i, "releasing ")
assert(lock1:release()) -- by now the 2nd 500 timed out
--print(i, "destroying ")
@@ -69,7 +69,7 @@ copas.loop(function()
--print(i, "timed out!")
timeout_count = timeout_count + 1
--if i == (size*2)/3 then
- -- copas.sleep(2) -- to ensure thread 500 finished its sleep above
+ -- copas.pause(2) -- to ensure thread 500 finished its sleep above
--end
tracker[i] = nil
@@ -88,7 +88,7 @@ copas.loop(function()
print("releasing "..size.." threads...", gettime())
assert(lock1:release())
print("waiting to finish...")
- while next(tracker) do copas.sleep(0.1) end
+ while next(tracker) do copas.pause(0.1) end
-- check results
print("success: ", success_count)
print("timeout: ", timeout_count)
diff --git a/tests/sleep.lua b/tests/pause.lua
similarity index 91%
rename from tests/sleep.lua
rename to tests/pause.lua
index e04cd0f..385dda8 100644
--- a/tests/sleep.lua
+++ b/tests/pause.lua
@@ -7,7 +7,7 @@ local copas = require("copas")
local t1 = copas.addthread(
function()
- copas.sleep(-1) -- sleep until woken up
+ copas.pauseforever() -- sleep until woken up
end
)
diff --git a/tests/queue.lua b/tests/queue.lua
index 67f2e41..9329a60 100644
--- a/tests/queue.lua
+++ b/tests/queue.lua
@@ -19,7 +19,7 @@ copas.loop(function()
-- yielding on pop when queue is empty
local s = now()
copas.addthread(function()
- copas.sleep(0.5)
+ copas.pause(0.5)
q:push("delayed")
end)
assert(q:pop() == "delayed", "expected a delayed result")
@@ -53,7 +53,7 @@ copas.loop(function()
local coro = q:add_worker(function(item)
count = count + 1
end)
- copas.sleep(0.1)
+ copas.pause(0.1)
assert(count == 3, "expected all 3 items handled")
assert(coroutine.status(coro) == "dead", "expected thread to be gone")
-- coro should be GC'able
@@ -86,7 +86,7 @@ print("test 1 success!")
copas.loop(function()
local q = Queue:new()
q:add_worker(function() end)
- copas.sleep(0.5) -- to activate the worker, which will now be blocked on the q semaphore
+ copas.pause(0.5) -- to activate the worker, which will now be blocked on the q semaphore
q:stop() -- this should exit the idle workers and exit the copas loop
end)
diff --git a/tests/removeserver.lua b/tests/removeserver.lua
index a98cdc0..cf6a280 100644
--- a/tests/removeserver.lua
+++ b/tests/removeserver.lua
@@ -33,7 +33,7 @@ copas.addthread(function()
for i = 1, 3 do
wait_for_trigger()
trigger_it(i)
- copas.sleep(0.1)
+ copas.pause(0.1)
end
end)
diff --git a/tests/removethread.lua b/tests/removethread.lua
index 0e36818..ec1d14a 100644
--- a/tests/removethread.lua
+++ b/tests/removethread.lua
@@ -13,13 +13,13 @@ local t1 = copas.addthread(
while true do
n = n + 1
print("endless thread:",n)
- copas.sleep(0.5)
+ copas.pause(0.5)
end
end)
local t2 = copas.addthread(function()
for i = 1, 5 do
- copas.sleep(0.6)
+ copas.pause(0.6)
end
print("stopping endless thread externally")
copas.removethread(t1)
diff --git a/tests/request.lua b/tests/request.lua
index 3fdcfec..3d73135 100644
--- a/tests/request.lua
+++ b/tests/request.lua
@@ -25,7 +25,7 @@ end
copas.addthread(function()
while switches < max_switches do
- copas.sleep(0)
+ copas.pause()
switches = switches + 1
end
diff --git a/tests/semaphore.lua b/tests/semaphore.lua
index 4d15ed6..6559a43 100644
--- a/tests/semaphore.lua
+++ b/tests/semaphore.lua
@@ -52,18 +52,18 @@ copas.loop(function()
print("got the next 5!")
state = state + 2
end)
- copas.sleep(0.1)
+ copas.pause(0.1)
assert(state == 0, "expected state to still be 0")
assert(sema:get_count() == 2, "expected count to still have 2 resources")
assert(sema:give(4))
assert(sema:get_count() == 1, "expected count to now have 1 resource")
- copas.sleep(0.1)
+ copas.pause(0.1)
assert(state == 1, "expected 1 from the first thread to be added to state")
assert(sema:give(4))
assert(sema:get_count() == 0, "gave 4 more, so 5 in total, releasing 5, leaves 0 as expected")
- copas.sleep(0.1)
+ copas.pause(0.1)
assert(state == 3, "expected 2 from the 2nd thread to be added to state")
@@ -92,9 +92,9 @@ copas.loop(function()
state = state + 1
end
end)
- copas.sleep(0.1)
+ copas.pause(0.1)
assert(sema:destroy())
- copas.sleep(0.1)
+ copas.pause(0.1)
assert(state == 2, "expected 2 threads to error with 'destroyed'")
-- only returns errors from now on, on all methods
@@ -121,9 +121,9 @@ copas.loop(function()
state = state + 1
end
end)
- copas.sleep(0.1)
+ copas.pause(0.1)
assert(sema:destroy())
- copas.sleep(0.1)
+ copas.pause(0.1)
assert(state == 1, "expected 1 thread to error with 'destroyed'")
sema = nil
@@ -137,7 +137,7 @@ copas.loop(function()
collectgarbage() -- collect garbage to force eviction from the semaphore registry
collectgarbage()
- copas.sleep(0.5) -- wait for the timeout to expire if it is still set
+ copas.pause(0.5) -- wait for the timeout to expire if it is still set
assert(errors == 0, "expected no errors")
test_complete = true
diff --git a/tests/starve.lua b/tests/starve.lua
index 127ca19..6d07d3b 100644
--- a/tests/starve.lua
+++ b/tests/starve.lua
@@ -63,7 +63,7 @@ local function runtest()
local i = 0
local start = socket.gettime()
while done ~= 2 do
- copas.sleep(1) -- delta sleep, so it slowly diverges if starved
+ copas.pause(1) -- delta sleep, so it slowly diverges if starved
i = i + 1
local time_passed = socket.gettime()-start
print("slept "..i.." seconds, time passed: ".. time_passed.." seconds")
diff --git a/tests/timeout_errors.lua b/tests/timeout_errors.lua
index 70f2b98..d0411bd 100644
--- a/tests/timeout_errors.lua
+++ b/tests/timeout_errors.lua
@@ -23,7 +23,7 @@ function tests.error_on_timeout()
error("oops...")
end)
print "going to sleep for 1 second"
- copas.sleep(1)
+ copas.pause(1)
if not (err_received or ""):find("oops...", 1, true) then
print("expected to find the error string 'oops...', but got: " .. tostring(err_received))
diff --git a/tests/tls-sni.lua b/tests/tls-sni.lua
index 81a3cf8..94841b3 100644
--- a/tests/tls-sni.lua
+++ b/tests/tls-sni.lua
@@ -71,7 +71,7 @@ server = assert(socket.bind("*", port))
copas.addserver(server, copas.handler(echoHandler, server_params))
copas.addthread(function()
- copas.sleep(0.5) -- allow server socket to be ready
+ copas.pause(0.5) -- allow server socket to be ready
----------------------
-- Tests start here --