aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml67
-rw-r--r--CMakeLists.txt17
-rw-r--r--cmake/FindLua.cmake127
-rw-r--r--cmake/dist.cmake321
-rw-r--r--cmake/lua.cmake309
-rw-r--r--dist.info12
-rw-r--r--llthreads2/.gitignore18
-rw-r--r--llthreads2/.travis.yml42
-rw-r--r--llthreads2/.travis/setup_lua.sh35
-rw-r--r--llthreads2/CMakeLists.txt17
-rw-r--r--llthreads2/COPYRIGHT.llthreads19
-rw-r--r--llthreads2/LICENSE20
-rw-r--r--llthreads2/README.md113
-rw-r--r--llthreads2/cmake/FindLua.cmake127
-rw-r--r--llthreads2/cmake/dist.cmake321
-rw-r--r--llthreads2/cmake/lua.cmake309
-rw-r--r--llthreads2/dist.info12
-rw-r--r--llthreads2/lakeconfig.lua252
-rw-r--r--llthreads2/lakefile45
-rw-r--r--llthreads2/msvc/llthreads.sln20
-rw-r--r--llthreads2/msvc/llthreads.vcproj208
-rw-r--r--llthreads2/rockspecs/lua-llthreads2-0.1.0-1.rockspec44
-rw-r--r--llthreads2/rockspecs/lua-llthreads2-0.1.1-1.rockspec44
-rw-r--r--llthreads2/rockspecs/lua-llthreads2-compat-0.1.0-1.rockspec44
-rw-r--r--llthreads2/rockspecs/lua-llthreads2-compat-0.1.1-1.rockspec44
-rw-r--r--llthreads2/rockspecs/lua-llthreads2-compat-scm-0.rockspec44
-rw-r--r--llthreads2/rockspecs/lua-llthreads2-scm-0.rockspec44
-rw-r--r--llthreads2/src/copy.inc170
-rw-r--r--llthreads2/src/l52util.c126
-rw-r--r--llthreads2/src/l52util.h57
-rw-r--r--llthreads2/src/llthread.c746
-rw-r--r--llthreads2/src/traceback.inc56
-rw-r--r--llthreads2/test/test_alive.lua35
-rw-r--r--llthreads2/test/test_join_detach.lua59
-rw-r--r--llthreads2/test/test_join_error.lua24
-rw-r--r--llthreads2/test/test_join_timeout.lua23
-rw-r--r--llthreads2/test/test_llthreads.lua60
-rw-r--r--llthreads2/test/test_load_llthreads2.lua7
-rw-r--r--llthreads2/test/test_logger.lua24
-rw-r--r--llthreads2/test/test_pass_cfunction.lua17
-rw-r--r--llthreads2/test/test_register_ffi.lua14
-rw-r--r--llthreads2/test/test_register_llthreads.lua15
-rw-r--r--llthreads2/test/test_table_copy.lua134
-rw-r--r--llthreads2/test/test_threads.lua67
-rw-r--r--llthreads2/test/utils.lua63
45 files changed, 4372 insertions, 0 deletions
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..3bb3efa
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,67 @@
1#
2# LuaDist Travis-CI Hook
3#
4
5# We assume C build environments
6language: C
7
8# Try using multiple Lua Implementations
9env:
10 - TOOL="gcc" # Use native compiler (GCC usually)
11 - TOOL="clang" # Use clang
12 - TOOL="i686-w64-mingw32" # 32bit MinGW
13 - TOOL="x86_64-w64-mingw32" # 64bit MinGW
14 - TOOL="arm-linux-gnueabihf" # ARM hard-float (hf), linux
15
16# Crosscompile builds may fail
17matrix:
18 allow_failures:
19 - env: TOOL="i686-w64-mingw32"
20 - env: TOOL="x86_64-w64-mingw32"
21 - env: TOOL="arm-linux-gnueabihf"
22
23# Install dependencies
24install:
25 - git clone git://github.com/LuaDist/Tools.git ~/_tools
26 - ~/_tools/travis/travis install
27
28# Bootstap
29before_script:
30 - ~/_tools/travis/travis bootstrap
31
32# Build the module
33script:
34 # - ~/_tools/travis/travis build
35 - ~/luadist _test install lua-5.1.5 -binary=false -verbose -DCMAKE_TOOLCHAIN_FILE=$TOOLFILE
36 - ~/luadist _test make . -binary=false -verbose -DCMAKE_TOOLCHAIN_FILE=$TOOLFILE
37 - cd _test/share/lua-llthreads2/test
38 - $TRAVIS_BUILD_DIR/_test/bin/lua test_table_copy.lua
39 - $TRAVIS_BUILD_DIR/_test/bin/lua test_threads.lua
40 - $TRAVIS_BUILD_DIR/_test/bin/lua test_llthreads.lua
41 - $TRAVIS_BUILD_DIR/_test/bin/lua test_join_timeout.lua
42 - $TRAVIS_BUILD_DIR/_test/bin/lua test_join_detach.lua
43 - $TRAVIS_BUILD_DIR/_test/bin/lua test_join_error.lua
44 - $TRAVIS_BUILD_DIR/_test/bin/lua test_register_ffi.lua
45 - $TRAVIS_BUILD_DIR/_test/bin/lua test_logger.lua
46 - $TRAVIS_BUILD_DIR/_test/bin/lua test_pass_cfunction.lua
47 - $TRAVIS_BUILD_DIR/_test/bin/lua test_load_llthreads2.lua
48 - $TRAVIS_BUILD_DIR/_test/bin/lua test_alive.lua
49
50
51# Execute additional tests or commands
52after_script:
53 - cd $TRAVIS_BUILD_DIR
54 - ~/_tools/travis/travis test
55
56# Only watch the master branch
57branches:
58 only:
59 - dist-llthreads2
60
61# Notify the LuaDist Dev group if needed
62notifications:
63 recipients:
64 - luadist-dev@googlegroups.com
65 email:
66 on_success: change
67 on_failure: always
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..596e496
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,17 @@
1cmake_minimum_required ( VERSION 2.8 )
2
3project ( lua-llthreads2 C )
4include ( cmake/dist.cmake )
5include ( lua )
6
7set ( CMAKE_THREAD_PREFER_PTHREAD TRUE )
8include ( FindThreads )
9
10include_directories ( ${CMAKE_CURRENT_SOURCE_DIR}/llthreads2/src )
11
12set ( LUA_LLTHREADS_SRC llthreads2/src/l52util.c llthreads2/src/llthread.c )
13
14install_lua_module ( llthreads2 ${LUA_LLTHREADS_SRC} LINK ${CMAKE_THREAD_LIBS_INIT} )
15
16install_data ( llthreads2/COPYRIGHT.llthreads llthreads2/README.md llthreads2/LICENSE )
17install_test ( llthreads2/test/ )
diff --git a/cmake/FindLua.cmake b/cmake/FindLua.cmake
new file mode 100644
index 0000000..6991b4a
--- /dev/null
+++ b/cmake/FindLua.cmake
@@ -0,0 +1,127 @@
1# Locate Lua library
2# This module defines
3# LUA_EXECUTABLE, if found
4# LUA_FOUND, if false, do not try to link to Lua
5# LUA_LIBRARIES
6# LUA_INCLUDE_DIR, where to find lua.h
7# LUA_VERSION_STRING, the version of Lua found (since CMake 2.8.8)
8#
9# Note that the expected include convention is
10# #include "lua.h"
11# and not
12# #include <lua/lua.h>
13# This is because, the lua location is not standardized and may exist
14# in locations other than lua/
15
16#=============================================================================
17# Copyright 2007-2009 Kitware, Inc.
18# Modified to support Lua 5.2 by LuaDist 2012
19#
20# Distributed under the OSI-approved BSD License (the "License");
21# see accompanying file Copyright.txt for details.
22#
23# This software is distributed WITHOUT ANY WARRANTY; without even the
24# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
25# See the License for more information.
26#=============================================================================
27# (To distribute this file outside of CMake, substitute the full
28# License text for the above reference.)
29#
30# The required version of Lua can be specified using the
31# standard syntax, e.g. FIND_PACKAGE(Lua 5.1)
32# Otherwise the module will search for any available Lua implementation
33
34# Always search for non-versioned lua first (recommended)
35SET(_POSSIBLE_LUA_INCLUDE include include/lua)
36SET(_POSSIBLE_LUA_EXECUTABLE lua)
37SET(_POSSIBLE_LUA_LIBRARY lua)
38
39# Determine possible naming suffixes (there is no standard for this)
40IF(Lua_FIND_VERSION_MAJOR AND Lua_FIND_VERSION_MINOR)
41 SET(_POSSIBLE_SUFFIXES "${Lua_FIND_VERSION_MAJOR}${Lua_FIND_VERSION_MINOR}" "${Lua_FIND_VERSION_MAJOR}.${Lua_FIND_VERSION_MINOR}" "-${Lua_FIND_VERSION_MAJOR}.${Lua_FIND_VERSION_MINOR}")
42ELSE(Lua_FIND_VERSION_MAJOR AND Lua_FIND_VERSION_MINOR)
43 SET(_POSSIBLE_SUFFIXES "52" "5.2" "-5.2" "51" "5.1" "-5.1")
44ENDIF(Lua_FIND_VERSION_MAJOR AND Lua_FIND_VERSION_MINOR)
45
46# Set up possible search names and locations
47FOREACH(_SUFFIX ${_POSSIBLE_SUFFIXES})
48 LIST(APPEND _POSSIBLE_LUA_INCLUDE "include/lua${_SUFFIX}")
49 LIST(APPEND _POSSIBLE_LUA_EXECUTABLE "lua${_SUFFIX}")
50 LIST(APPEND _POSSIBLE_LUA_LIBRARY "lua${_SUFFIX}")
51ENDFOREACH(_SUFFIX)
52
53# Find the lua executable
54FIND_PROGRAM(LUA_EXECUTABLE
55 NAMES ${_POSSIBLE_LUA_EXECUTABLE}
56)
57
58# Find the lua header
59FIND_PATH(LUA_INCLUDE_DIR lua.h
60 HINTS
61 $ENV{LUA_DIR}
62 PATH_SUFFIXES ${_POSSIBLE_LUA_INCLUDE}
63 PATHS
64 ~/Library/Frameworks
65 /Library/Frameworks
66 /usr/local
67 /usr
68 /sw # Fink
69 /opt/local # DarwinPorts
70 /opt/csw # Blastwave
71 /opt
72)
73
74# Find the lua library
75FIND_LIBRARY(LUA_LIBRARY
76 NAMES ${_POSSIBLE_LUA_LIBRARY}
77 HINTS
78 $ENV{LUA_DIR}
79 PATH_SUFFIXES lib64 lib
80 PATHS
81 ~/Library/Frameworks
82 /Library/Frameworks
83 /usr/local
84 /usr
85 /sw
86 /opt/local
87 /opt/csw
88 /opt
89)
90
91IF(LUA_LIBRARY)
92 # include the math library for Unix
93 IF(UNIX AND NOT APPLE)
94 FIND_LIBRARY(LUA_MATH_LIBRARY m)
95 SET( LUA_LIBRARIES "${LUA_LIBRARY};${LUA_MATH_LIBRARY}" CACHE STRING "Lua Libraries")
96 # For Windows and Mac, don't need to explicitly include the math library
97 ELSE(UNIX AND NOT APPLE)
98 SET( LUA_LIBRARIES "${LUA_LIBRARY}" CACHE STRING "Lua Libraries")
99 ENDIF(UNIX AND NOT APPLE)
100ENDIF(LUA_LIBRARY)
101
102# Determine Lua version
103IF(LUA_INCLUDE_DIR AND EXISTS "${LUA_INCLUDE_DIR}/lua.h")
104 FILE(STRINGS "${LUA_INCLUDE_DIR}/lua.h" lua_version_str REGEX "^#define[ \t]+LUA_RELEASE[ \t]+\"Lua .+\"")
105
106 STRING(REGEX REPLACE "^#define[ \t]+LUA_RELEASE[ \t]+\"Lua ([^\"]+)\".*" "\\1" LUA_VERSION_STRING "${lua_version_str}")
107 UNSET(lua_version_str)
108ENDIF()
109
110# Lua 5.2
111IF(NOT LUA_VERSION_STRING)
112 FILE(STRINGS "${LUA_INCLUDE_DIR}/lua.h" lua_version_str REGEX "^#define LUA_VERSION_[A-Z]+[ \t]+\"[0-9]+\"")
113 STRING(REGEX REPLACE ".*#define LUA_VERSION_MAJOR[ \t]+\"([0-9]+)\".*" "\\1" LUA_VERSION_MAJOR ${lua_version_str})
114 STRING(REGEX REPLACE ".*#define LUA_VERSION_MINOR[ \t]+\"([0-9]+)\".*" "\\1" LUA_VERSION_MINOR ${lua_version_str})
115 STRING(REGEX REPLACE ".*#define LUA_VERSION_RELEASE[ \t]+\"([0-9]+)\".*" "\\1" LUA_VERSION_RELEASE ${lua_version_str})
116 SET(LUA_VERSION_STRING ${LUA_VERSION_MAJOR}.${LUA_VERSION_MINOR}.${LUA_VERSION_RELEASE})
117ENDIF()
118
119INCLUDE(FindPackageHandleStandardArgs)
120# handle the QUIETLY and REQUIRED arguments and set LUA_FOUND to TRUE if
121# all listed variables are TRUE
122FIND_PACKAGE_HANDLE_STANDARD_ARGS(Lua
123 REQUIRED_VARS LUA_LIBRARIES LUA_INCLUDE_DIR
124 VERSION_VAR LUA_VERSION_STRING)
125
126MARK_AS_ADVANCED(LUA_INCLUDE_DIR LUA_LIBRARIES LUA_LIBRARY LUA_MATH_LIBRARY LUA_EXECUTABLE)
127
diff --git a/cmake/dist.cmake b/cmake/dist.cmake
new file mode 100644
index 0000000..310ef94
--- /dev/null
+++ b/cmake/dist.cmake
@@ -0,0 +1,321 @@
1# LuaDist CMake utility library.
2# Provides sane project defaults and macros common to LuaDist CMake builds.
3#
4# Copyright (C) 2007-2012 LuaDist.
5# by David Manura, Peter Drahoš
6# Redistribution and use of this file is allowed according to the terms of the MIT license.
7# For details see the COPYRIGHT file distributed with LuaDist.
8# Please note that the package source code is licensed under its own license.
9
10## Extract information from dist.info
11if ( NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/dist.info )
12 message ( FATAL_ERROR
13 "Missing dist.info file (${CMAKE_CURRENT_SOURCE_DIR}/dist.info)." )
14endif ()
15file ( READ ${CMAKE_CURRENT_SOURCE_DIR}/dist.info DIST_INFO )
16if ( "${DIST_INFO}" STREQUAL "" )
17 message ( FATAL_ERROR "Failed to load dist.info." )
18endif ()
19# Reads field `name` from dist.info string `DIST_INFO` into variable `var`.
20macro ( _parse_dist_field name var )
21 string ( REGEX REPLACE ".*${name}[ \t]?=[ \t]?[\"']([^\"']+)[\"'].*" "\\1"
22 ${var} "${DIST_INFO}" )
23 if ( ${var} STREQUAL DIST_INFO )
24 message ( FATAL_ERROR "Failed to extract \"${var}\" from dist.info" )
25 endif ()
26endmacro ()
27#
28_parse_dist_field ( name DIST_NAME )
29_parse_dist_field ( version DIST_VERSION )
30_parse_dist_field ( license DIST_LICENSE )
31_parse_dist_field ( author DIST_AUTHOR )
32_parse_dist_field ( maintainer DIST_MAINTAINER )
33_parse_dist_field ( url DIST_URL )
34_parse_dist_field ( desc DIST_DESC )
35message ( "DIST_NAME: ${DIST_NAME}")
36message ( "DIST_VERSION: ${DIST_VERSION}")
37message ( "DIST_LICENSE: ${DIST_LICENSE}")
38message ( "DIST_AUTHOR: ${DIST_AUTHOR}")
39message ( "DIST_MAINTAINER: ${DIST_MAINTAINER}")
40message ( "DIST_URL: ${DIST_URL}")
41message ( "DIST_DESC: ${DIST_DESC}")
42string ( REGEX REPLACE ".*depends[ \t]?=[ \t]?[\"']([^\"']+)[\"'].*" "\\1"
43 DIST_DEPENDS ${DIST_INFO} )
44if ( DIST_DEPENDS STREQUAL DIST_INFO )
45 set ( DIST_DEPENDS "" )
46endif ()
47message ( "DIST_DEPENDS: ${DIST_DEPENDS}")
48## 2DO: Parse DIST_DEPENDS and try to install Dependencies with automatically using externalproject_add
49
50
51## INSTALL DEFAULTS (Relative to CMAKE_INSTALL_PREFIX)
52# Primary paths
53set ( INSTALL_BIN bin CACHE PATH "Where to install binaries to." )
54set ( INSTALL_LIB lib CACHE PATH "Where to install libraries to." )
55set ( INSTALL_INC include CACHE PATH "Where to install headers to." )
56set ( INSTALL_ETC etc CACHE PATH "Where to store configuration files" )
57set ( INSTALL_SHARE share CACHE PATH "Directory for shared data." )
58
59# Secondary paths
60option ( INSTALL_VERSION
61 "Install runtime libraries and executables with version information." OFF)
62set ( INSTALL_DATA ${INSTALL_SHARE}/${DIST_NAME} CACHE PATH
63 "Directory the package can store documentation, tests or other data in.")
64set ( INSTALL_DOC ${INSTALL_DATA}/doc CACHE PATH
65 "Recommended directory to install documentation into.")
66set ( INSTALL_EXAMPLE ${INSTALL_DATA}/example CACHE PATH
67 "Recommended directory to install examples into.")
68set ( INSTALL_TEST ${INSTALL_DATA}/test CACHE PATH
69 "Recommended directory to install tests into.")
70set ( INSTALL_FOO ${INSTALL_DATA}/etc CACHE PATH
71 "Where to install additional files")
72
73# Tweaks and other defaults
74# Setting CMAKE to use loose block and search for find modules in source directory
75set ( CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS true )
76set ( CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH} )
77option ( BUILD_SHARED_LIBS "Build shared libraries" ON )
78
79# In MSVC, prevent warnings that can occur when using standard libraries.
80if ( MSVC )
81 add_definitions ( -D_CRT_SECURE_NO_WARNINGS )
82endif ()
83
84# RPath and relative linking
85option ( USE_RPATH "Use relative linking." ON)
86if ( USE_RPATH )
87 string ( REGEX REPLACE "[^!/]+" ".." UP_DIR ${INSTALL_BIN} )
88 set ( CMAKE_SKIP_BUILD_RPATH FALSE CACHE STRING "" FORCE )
89 set ( CMAKE_BUILD_WITH_INSTALL_RPATH FALSE CACHE STRING "" FORCE )
90 set ( CMAKE_INSTALL_RPATH $ORIGIN/${UP_DIR}/${INSTALL_LIB}
91 CACHE STRING "" FORCE )
92 set ( CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE CACHE STRING "" FORCE )
93 set ( CMAKE_INSTALL_NAME_DIR @executable_path/${UP_DIR}/${INSTALL_LIB}
94 CACHE STRING "" FORCE )
95endif ()
96
97## MACROS
98# Parser macro
99macro ( parse_arguments prefix arg_names option_names)
100 set ( DEFAULT_ARGS )
101 foreach ( arg_name ${arg_names} )
102 set ( ${prefix}_${arg_name} )
103 endforeach ()
104 foreach ( option ${option_names} )
105 set ( ${prefix}_${option} FALSE )
106 endforeach ()
107
108 set ( current_arg_name DEFAULT_ARGS )
109 set ( current_arg_list )
110 foreach ( arg ${ARGN} )
111 set ( larg_names ${arg_names} )
112 list ( FIND larg_names "${arg}" is_arg_name )
113 if ( is_arg_name GREATER -1 )
114 set ( ${prefix}_${current_arg_name} ${current_arg_list} )
115 set ( current_arg_name ${arg} )
116 set ( current_arg_list )
117 else ()
118 set ( loption_names ${option_names} )
119 list ( FIND loption_names "${arg}" is_option )
120 if ( is_option GREATER -1 )
121 set ( ${prefix}_${arg} TRUE )
122 else ()
123 set ( current_arg_list ${current_arg_list} ${arg} )
124 endif ()
125 endif ()
126 endforeach ()
127 set ( ${prefix}_${current_arg_name} ${current_arg_list} )
128endmacro ()
129
130
131# install_executable ( executable_targets )
132# Installs any executables generated using "add_executable".
133# USE: install_executable ( lua )
134# NOTE: subdirectories are NOT supported
135set ( CPACK_COMPONENT_RUNTIME_DISPLAY_NAME "${DIST_NAME} Runtime" )
136set ( CPACK_COMPONENT_RUNTIME_DESCRIPTION
137 "Executables and runtime libraries. Installed into ${INSTALL_BIN}." )
138macro ( install_executable )
139 foreach ( _file ${ARGN} )
140 if ( INSTALL_VERSION )
141 set_target_properties ( ${_file} PROPERTIES VERSION ${DIST_VERSION}
142 SOVERSION ${DIST_VERSION} )
143 endif ()
144 install ( TARGETS ${_file} RUNTIME DESTINATION ${INSTALL_BIN}
145 COMPONENT Runtime )
146 endforeach()
147endmacro ()
148
149# install_library ( library_targets )
150# Installs any libraries generated using "add_library" into apropriate places.
151# USE: install_library ( libexpat )
152# NOTE: subdirectories are NOT supported
153set ( CPACK_COMPONENT_LIBRARY_DISPLAY_NAME "${DIST_NAME} Development Libraries" )
154set ( CPACK_COMPONENT_LIBRARY_DESCRIPTION
155 "Static and import libraries needed for development. Installed into ${INSTALL_LIB} or ${INSTALL_BIN}." )
156macro ( install_library )
157 foreach ( _file ${ARGN} )
158 if ( INSTALL_VERSION )
159 set_target_properties ( ${_file} PROPERTIES VERSION ${DIST_VERSION}
160 SOVERSION ${DIST_VERSION} )
161 endif ()
162 install ( TARGETS ${_file}
163 RUNTIME DESTINATION ${INSTALL_BIN} COMPONENT Runtime
164 LIBRARY DESTINATION ${INSTALL_LIB} COMPONENT Runtime
165 ARCHIVE DESTINATION ${INSTALL_LIB} COMPONENT Library )
166 endforeach()
167endmacro ()
168
169# helper function for various install_* functions, for PATTERN/REGEX args.
170macro ( _complete_install_args )
171 if ( NOT("${_ARG_PATTERN}" STREQUAL "") )
172 set ( _ARG_PATTERN PATTERN ${_ARG_PATTERN} )
173 endif ()
174 if ( NOT("${_ARG_REGEX}" STREQUAL "") )
175 set ( _ARG_REGEX REGEX ${_ARG_REGEX} )
176 endif ()
177endmacro ()
178
179# install_header ( files/directories [INTO destination] )
180# Install a directories or files into header destination.
181# USE: install_header ( lua.h luaconf.h ) or install_header ( GL )
182# USE: install_header ( mylib.h INTO mylib )
183# For directories, supports optional PATTERN/REGEX arguments like install().
184set ( CPACK_COMPONENT_HEADER_DISPLAY_NAME "${DIST_NAME} Development Headers" )
185set ( CPACK_COMPONENT_HEADER_DESCRIPTION
186 "Headers needed for development. Installed into ${INSTALL_INC}." )
187macro ( install_header )
188 parse_arguments ( _ARG "INTO;PATTERN;REGEX" "" ${ARGN} )
189 _complete_install_args()
190 foreach ( _file ${_ARG_DEFAULT_ARGS} )
191 if ( IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/${_file}" )
192 install ( DIRECTORY ${_file} DESTINATION ${INSTALL_INC}/${_ARG_INTO}
193 COMPONENT Header ${_ARG_PATTERN} ${_ARG_REGEX} )
194 else ()
195 install ( FILES ${_file} DESTINATION ${INSTALL_INC}/${_ARG_INTO}
196 COMPONENT Header )
197 endif ()
198 endforeach()
199endmacro ()
200
201# install_data ( files/directories [INTO destination] )
202# This installs additional data files or directories.
203# USE: install_data ( extra data.dat )
204# USE: install_data ( image1.png image2.png INTO images )
205# For directories, supports optional PATTERN/REGEX arguments like install().
206set ( CPACK_COMPONENT_DATA_DISPLAY_NAME "${DIST_NAME} Data" )
207set ( CPACK_COMPONENT_DATA_DESCRIPTION
208 "Application data. Installed into ${INSTALL_DATA}." )
209macro ( install_data )
210 parse_arguments ( _ARG "INTO;PATTERN;REGEX" "" ${ARGN} )
211 _complete_install_args()
212 foreach ( _file ${_ARG_DEFAULT_ARGS} )
213 if ( IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/${_file}" )
214 install ( DIRECTORY ${_file}
215 DESTINATION ${INSTALL_DATA}/${_ARG_INTO}
216 COMPONENT Data ${_ARG_PATTERN} ${_ARG_REGEX} )
217 else ()
218 install ( FILES ${_file} DESTINATION ${INSTALL_DATA}/${_ARG_INTO}
219 COMPONENT Data )
220 endif ()
221 endforeach()
222endmacro ()
223
224# INSTALL_DOC ( files/directories [INTO destination] )
225# This installs documentation content
226# USE: install_doc ( doc/ doc.pdf )
227# USE: install_doc ( index.html INTO html )
228# For directories, supports optional PATTERN/REGEX arguments like install().
229set ( CPACK_COMPONENT_DOCUMENTATION_DISPLAY_NAME "${DIST_NAME} Documentation" )
230set ( CPACK_COMPONENT_DOCUMENTATION_DESCRIPTION
231 "Application documentation. Installed into ${INSTALL_DOC}." )
232macro ( install_doc )
233 parse_arguments ( _ARG "INTO;PATTERN;REGEX" "" ${ARGN} )
234 _complete_install_args()
235 foreach ( _file ${_ARG_DEFAULT_ARGS} )
236 if ( IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/${_file}" )
237 install ( DIRECTORY ${_file} DESTINATION ${INSTALL_DOC}/${_ARG_INTO}
238 COMPONENT Documentation ${_ARG_PATTERN} ${_ARG_REGEX} )
239 else ()
240 install ( FILES ${_file} DESTINATION ${INSTALL_DOC}/${_ARG_INTO}
241 COMPONENT Documentation )
242 endif ()
243 endforeach()
244endmacro ()
245
246# install_example ( files/directories [INTO destination] )
247# This installs additional examples
248# USE: install_example ( examples/ exampleA )
249# USE: install_example ( super_example super_data INTO super)
250# For directories, supports optional PATTERN/REGEX argument like install().
251set ( CPACK_COMPONENT_EXAMPLE_DISPLAY_NAME "${DIST_NAME} Examples" )
252set ( CPACK_COMPONENT_EXAMPLE_DESCRIPTION
253 "Examples and their associated data. Installed into ${INSTALL_EXAMPLE}." )
254macro ( install_example )
255 parse_arguments ( _ARG "INTO;PATTERN;REGEX" "" ${ARGN} )
256 _complete_install_args()
257 foreach ( _file ${_ARG_DEFAULT_ARGS} )
258 if ( IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/${_file}" )
259 install ( DIRECTORY ${_file} DESTINATION ${INSTALL_EXAMPLE}/${_ARG_INTO}
260 COMPONENT Example ${_ARG_PATTERN} ${_ARG_REGEX} )
261 else ()
262 install ( FILES ${_file} DESTINATION ${INSTALL_EXAMPLE}/${_ARG_INTO}
263 COMPONENT Example )
264 endif ()
265 endforeach()
266endmacro ()
267
268# install_test ( files/directories [INTO destination] )
269# This installs tests and test files, DOES NOT EXECUTE TESTS
270# USE: install_test ( my_test data.sql )
271# USE: install_test ( feature_x_test INTO x )
272# For directories, supports optional PATTERN/REGEX argument like install().
273set ( CPACK_COMPONENT_TEST_DISPLAY_NAME "${DIST_NAME} Tests" )
274set ( CPACK_COMPONENT_TEST_DESCRIPTION
275 "Tests and associated data. Installed into ${INSTALL_TEST}." )
276macro ( install_test )
277 parse_arguments ( _ARG "INTO;PATTERN;REGEX" "" ${ARGN} )
278 _complete_install_args()
279 foreach ( _file ${_ARG_DEFAULT_ARGS} )
280 if ( IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/${_file}" )
281 install ( DIRECTORY ${_file} DESTINATION ${INSTALL_TEST}/${_ARG_INTO}
282 COMPONENT Test ${_ARG_PATTERN} ${_ARG_REGEX} )
283 else ()
284 install ( FILES ${_file} DESTINATION ${INSTALL_TEST}/${_ARG_INTO}
285 COMPONENT Test )
286 endif ()
287 endforeach()
288endmacro ()
289
290# install_foo ( files/directories [INTO destination] )
291# This installs optional or otherwise unneeded content
292# USE: install_foo ( etc/ example.doc )
293# USE: install_foo ( icon.png logo.png INTO icons)
294# For directories, supports optional PATTERN/REGEX argument like install().
295set ( CPACK_COMPONENT_OTHER_DISPLAY_NAME "${DIST_NAME} Unspecified Content" )
296set ( CPACK_COMPONENT_OTHER_DESCRIPTION
297 "Other unspecified content. Installed into ${INSTALL_FOO}." )
298macro ( install_foo )
299 parse_arguments ( _ARG "INTO;PATTERN;REGEX" "" ${ARGN} )
300 _complete_install_args()
301 foreach ( _file ${_ARG_DEFAULT_ARGS} )
302 if ( IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/${_file}" )
303 install ( DIRECTORY ${_file} DESTINATION ${INSTALL_FOO}/${_ARG_INTO}
304 COMPONENT Other ${_ARG_PATTERN} ${_ARG_REGEX} )
305 else ()
306 install ( FILES ${_file} DESTINATION ${INSTALL_FOO}/${_ARG_INTO}
307 COMPONENT Other )
308 endif ()
309 endforeach()
310endmacro ()
311
312## CTest defaults
313
314## CPack defaults
315set ( CPACK_GENERATOR "ZIP" )
316set ( CPACK_STRIP_FILES TRUE )
317set ( CPACK_PACKAGE_NAME "${DIST_NAME}" )
318set ( CPACK_PACKAGE_VERSION "${DIST_VERSION}")
319set ( CPACK_PACKAGE_VENDOR "LuaDist" )
320set ( CPACK_COMPONENTS_ALL Runtime Library Header Data Documentation Example Other )
321include ( CPack )
diff --git a/cmake/lua.cmake b/cmake/lua.cmake
new file mode 100644
index 0000000..ee2e35d
--- /dev/null
+++ b/cmake/lua.cmake
@@ -0,0 +1,309 @@
1# LuaDist CMake utility library for Lua.
2#
3# Copyright (C) 2007-2012 LuaDist.
4# by David Manura, Peter Drahos
5# Redistribution and use of this file is allowed according to the terms of the MIT license.
6# For details see the COPYRIGHT file distributed with LuaDist.
7# Please note that the package source code is licensed under its own license.
8
9set ( INSTALL_LMOD ${INSTALL_LIB}/lua
10 CACHE PATH "Directory to install Lua modules." )
11set ( INSTALL_CMOD ${INSTALL_LIB}/lua
12 CACHE PATH "Directory to install Lua binary modules." )
13
14option ( LUA_SKIP_WRAPPER
15 "Do not build and install Lua executable wrappers." OFF )
16option ( LUA_STATIC_MODULE "Build modules for static linking" OFF )
17
18# List of (Lua module name, file path) pairs.
19# Used internally by add_lua_test. Built by add_lua_module.
20set ( _lua_modules )
21
22# utility function: appends path `path` to path `basepath`, properly
23# handling cases when `path` may be relative or absolute.
24macro ( _append_path basepath path result )
25 if ( IS_ABSOLUTE "${path}" )
26 set ( ${result} "${path}" )
27 else ()
28 set ( ${result} "${basepath}/${path}" )
29 endif ()
30endmacro ()
31
32# install_lua_executable ( target source )
33# Automatically generate a binary if srlua package is available
34# The application or its source will be placed into /bin
35# If the application source did not have .lua suffix then it will be added
36# USE: lua_executable ( sputnik src/sputnik.lua )
37macro ( install_lua_executable _name _source )
38 get_filename_component ( _source_name ${_source} NAME_WE )
39 # Find srlua and glue
40 find_program( SRLUA_EXECUTABLE NAMES srlua )
41 find_program( GLUE_EXECUTABLE NAMES glue )
42 # Executable output
43 set ( _exe ${CMAKE_CURRENT_BINARY_DIR}/${_name}${CMAKE_EXECUTABLE_SUFFIX} )
44 if ( NOT SKIP_LUA_WRAPPER AND SRLUA_EXECUTABLE AND GLUE_EXECUTABLE )
45 # Generate binary gluing the lua code to srlua, this is a robuust approach for most systems
46 add_custom_command(
47 OUTPUT ${_exe}
48 COMMAND ${GLUE_EXECUTABLE}
49 ARGS ${SRLUA_EXECUTABLE} ${_source} ${_exe}
50 DEPENDS ${_source}
51 WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
52 VERBATIM
53 )
54 # Make sure we have a target associated with the binary
55 add_custom_target(${_name} ALL
56 DEPENDS ${_exe}
57 )
58 # Install with run permissions
59 install ( PROGRAMS ${_exe} DESTINATION ${INSTALL_BIN} COMPONENT Runtime)
60 # Also install source as optional resurce
61 install ( FILES ${_source} DESTINATION ${INSTALL_FOO} COMPONENT Other )
62 else()
63 # Install into bin as is but without the lua suffix, we assume the executable uses UNIX shebang/hash-bang magic
64 install ( PROGRAMS ${_source} DESTINATION ${INSTALL_BIN}
65 RENAME ${_source_name}
66 COMPONENT Runtime
67 )
68 endif()
69endmacro ()
70
71macro ( _lua_module_helper is_install _name )
72 parse_arguments ( _MODULE "LINK;ALL_IN_ONE" "" ${ARGN} )
73 # _target is CMake-compatible target name for module (e.g. socket_core).
74 # _module is relative path of target (e.g. socket/core),
75 # without extension (e.g. .lua/.so/.dll).
76 # _MODULE_SRC is list of module source files (e.g. .lua and .c files).
77 # _MODULE_NAMES is list of module names (e.g. socket.core).
78 if ( _MODULE_ALL_IN_ONE )
79 string ( REGEX REPLACE "\\..*" "" _target "${_name}" )
80 string ( REGEX REPLACE "\\..*" "" _module "${_name}" )
81 set ( _target "${_target}_all_in_one")
82 set ( _MODULE_SRC ${_MODULE_ALL_IN_ONE} )
83 set ( _MODULE_NAMES ${_name} ${_MODULE_DEFAULT_ARGS} )
84 else ()
85 string ( REPLACE "." "_" _target "${_name}" )
86 string ( REPLACE "." "/" _module "${_name}" )
87 set ( _MODULE_SRC ${_MODULE_DEFAULT_ARGS} )
88 set ( _MODULE_NAMES ${_name} )
89 endif ()
90 if ( NOT _MODULE_SRC )
91 message ( FATAL_ERROR "no module sources specified" )
92 endif ()
93 list ( GET _MODULE_SRC 0 _first_source )
94
95 get_filename_component ( _ext ${_first_source} EXT )
96 if ( _ext STREQUAL ".lua" ) # Lua source module
97 list ( LENGTH _MODULE_SRC _len )
98 if ( _len GREATER 1 )
99 message ( FATAL_ERROR "more than one source file specified" )
100 endif ()
101
102 set ( _module "${_module}.lua" )
103
104 get_filename_component ( _module_dir ${_module} PATH )
105 get_filename_component ( _module_filename ${_module} NAME )
106 _append_path ( "${CMAKE_CURRENT_SOURCE_DIR}" "${_first_source}" _module_path )
107 list ( APPEND _lua_modules "${_name}" "${_module_path}" )
108
109 if ( ${is_install} )
110 install ( FILES ${_first_source} DESTINATION ${INSTALL_LMOD}/${_module_dir}
111 RENAME ${_module_filename}
112 COMPONENT Runtime
113 )
114 endif ()
115 else () # Lua C binary module
116 enable_language ( C )
117 find_package ( Lua REQUIRED )
118 include_directories ( ${LUA_INCLUDE_DIR} )
119
120 set ( _module "${_module}${CMAKE_SHARED_MODULE_SUFFIX}" )
121
122 get_filename_component ( _module_dir ${_module} PATH )
123 get_filename_component ( _module_filenamebase ${_module} NAME_WE )
124 foreach ( _thisname ${_MODULE_NAMES} )
125 list ( APPEND _lua_modules "${_thisname}"
126 "${CMAKE_CURRENT_BINARY_DIR}/\${CMAKE_CFG_INTDIR}/${_module}" )
127 endforeach ()
128
129 # Static module (not linking to lua)
130 if ( LUA_STATIC_MODULE )
131 add_library( ${_target} STATIC ${_MODULE_SRC})
132 target_link_libraries ( ${_target} ${_MODULE_LINK} )
133 else ()
134 # Dynamic module
135 add_library( ${_target} MODULE ${_MODULE_SRC})
136 target_link_libraries ( ${_target} ${LUA_LIBRARY} ${_MODULE_LINK} )
137 endif ()
138
139 set_target_properties ( ${_target} PROPERTIES
140 ARCHIVE_OUTPUT_DIRECTORY "${_module_dir}"
141 LIBRARY_OUTPUT_DIRECTORY "${_module_dir}"
142 PREFIX ""
143 OUTPUT_NAME "${_module_filenamebase}" )
144 if ( ${is_install} )
145 install ( TARGETS ${_target}
146 LIBRARY DESTINATION ${INSTALL_CMOD}/${_module_dir}
147 COMPONENT Runtime
148 ARCHIVE DESTINATION ${INSTALL_CMOD}/${_module_dir}
149 COMPONENT Library )
150 endif ()
151 endif ()
152endmacro ()
153
154# add_lua_module
155# Builds a Lua source module into a destination locatable by Lua
156# require syntax.
157# Binary modules are also supported where this function takes sources and
158# libraries to compile separated by LINK keyword.
159# USE: add_lua_module ( socket.http src/http.lua )
160# USE2: add_lua_module ( mime.core src/mime.c )
161# USE3: add_lua_module ( socket.core ${SRC_SOCKET} LINK ${LIB_SOCKET} )
162# USE4: add_lua_module ( ssl.context ssl.core ALL_IN_ONE src/context.c src/ssl.c )
163# This form builds an "all-in-one" module (e.g. ssl.so or ssl.dll containing
164# both modules ssl.context and ssl.core). The CMake target name will be
165# ssl_all_in_one.
166# Also sets variable _module_path (relative path where module typically
167# would be installed).
168macro ( add_lua_module )
169 _lua_module_helper ( 0 ${ARGN} )
170endmacro ()
171
172
173# install_lua_module
174# This is the same as `add_lua_module` but also installs the module.
175# USE: install_lua_module ( socket.http src/http.lua )
176# USE2: install_lua_module ( mime.core src/mime.c )
177# USE3: install_lua_module ( socket.core ${SRC_SOCKET} LINK ${LIB_SOCKET} )
178macro ( install_lua_module )
179 _lua_module_helper ( 1 ${ARGN} )
180endmacro ()
181
182# Builds string representing Lua table mapping Lua modules names to file
183# paths. Used internally.
184macro ( _make_module_table _outvar )
185 set ( ${_outvar} )
186 list ( LENGTH _lua_modules _n )
187 if ( ${_n} GREATER 0 ) # avoids cmake complaint
188 foreach ( _i RANGE 1 ${_n} 2 )
189 list ( GET _lua_modules ${_i} _path )
190 math ( EXPR _ii ${_i}-1 )
191 list ( GET _lua_modules ${_ii} _name )
192 set ( ${_outvar} "${_table} ['${_name}'] = '${_path}'\;\n")
193 endforeach ()
194 endif ()
195 set ( ${_outvar}
196"local modules = {
197${_table}}" )
198endmacro ()
199
200# add_lua_test ( _testfile [ WORKING_DIRECTORY _working_dir ] )
201# Runs Lua script `_testfile` under CTest tester.
202# Optional named argument `WORKING_DIRECTORY` is current working directory to
203# run test under (defaults to ${CMAKE_CURRENT_BINARY_DIR}).
204# Both paths, if relative, are relative to ${CMAKE_CURRENT_SOURCE_DIR}.
205# Any modules previously defined with install_lua_module are automatically
206# preloaded (via package.preload) prior to running the test script.
207# Under LuaDist, set test=true in config.lua to enable testing.
208# USE: add_lua_test ( test/test1.lua [args...] [WORKING_DIRECTORY dir])
209macro ( add_lua_test _testfile )
210 if ( NOT SKIP_TESTING )
211 parse_arguments ( _ARG "WORKING_DIRECTORY" "" ${ARGN} )
212 include ( CTest )
213 find_program ( LUA NAMES lua lua.bat )
214 get_filename_component ( TESTFILEABS ${_testfile} ABSOLUTE )
215 get_filename_component ( TESTFILENAME ${_testfile} NAME )
216 get_filename_component ( TESTFILEBASE ${_testfile} NAME_WE )
217
218 # Write wrapper script.
219 # Note: One simple way to allow the script to find modules is
220 # to just put them in package.preload.
221 set ( TESTWRAPPER ${CMAKE_CURRENT_BINARY_DIR}/${TESTFILENAME} )
222 _make_module_table ( _table )
223 set ( TESTWRAPPERSOURCE
224"local CMAKE_CFG_INTDIR = ... or '.'
225${_table}
226local function preload_modules(modules)
227 for name, path in pairs(modules) do
228 if path:match'%.lua' then
229 package.preload[name] = assert(loadfile(path))
230 else
231 local name = name:gsub('.*%-', '') -- remove any hyphen prefix
232 local symbol = 'luaopen_' .. name:gsub('%.', '_')
233 --improve: generalize to support all-in-one loader?
234 local path = path:gsub('%$%{CMAKE_CFG_INTDIR%}', CMAKE_CFG_INTDIR)
235 package.preload[name] = assert(package.loadlib(path, symbol))
236 end
237 end
238end
239preload_modules(modules)
240arg[0] = '${TESTFILEABS}'
241table.remove(arg, 1)
242return assert(loadfile '${TESTFILEABS}')(unpack(arg))
243" )
244 if ( _ARG_WORKING_DIRECTORY )
245 get_filename_component (
246 TESTCURRENTDIRABS ${_ARG_WORKING_DIRECTORY} ABSOLUTE )
247 # note: CMake 2.6 (unlike 2.8) lacks WORKING_DIRECTORY parameter.
248 set ( _pre ${CMAKE_COMMAND} -E chdir "${TESTCURRENTDIRABS}" )
249 endif ()
250 file ( WRITE ${TESTWRAPPER} ${TESTWRAPPERSOURCE})
251 add_test ( NAME ${TESTFILEBASE} COMMAND ${_pre} ${LUA}
252 ${TESTWRAPPER} "${CMAKE_CFG_INTDIR}"
253 ${_ARG_DEFAULT_ARGS} )
254 endif ()
255 # see also http://gdcm.svn.sourceforge.net/viewvc/gdcm/Sandbox/CMakeModules/UsePythonTest.cmake
256 # Note: ${CMAKE_CFG_INTDIR} is a command-line argument to allow proper
257 # expansion by the native build tool.
258endmacro ()
259
260
261# Converts Lua source file `_source` to binary string embedded in C source
262# file `_target`. Optionally compiles Lua source to byte code (not available
263# under LuaJIT2, which doesn't have a bytecode loader). Additionally, Lua
264# versions of bin2c [1] and luac [2] may be passed respectively as additional
265# arguments.
266#
267# [1] http://lua-users.org/wiki/BinToCee
268# [2] http://lua-users.org/wiki/LuaCompilerInLua
269function ( add_lua_bin2c _target _source )
270 find_program ( LUA NAMES lua lua.bat )
271 execute_process ( COMMAND ${LUA} -e "string.dump(function()end)"
272 RESULT_VARIABLE _LUA_DUMP_RESULT ERROR_QUIET )
273 if ( NOT ${_LUA_DUMP_RESULT} )
274 SET ( HAVE_LUA_DUMP true )
275 endif ()
276 message ( "-- string.dump=${HAVE_LUA_DUMP}" )
277
278 if ( ARGV2 )
279 get_filename_component ( BIN2C ${ARGV2} ABSOLUTE )
280 set ( BIN2C ${LUA} ${BIN2C} )
281 else ()
282 find_program ( BIN2C NAMES bin2c bin2c.bat )
283 endif ()
284 if ( HAVE_LUA_DUMP )
285 if ( ARGV3 )
286 get_filename_component ( LUAC ${ARGV3} ABSOLUTE )
287 set ( LUAC ${LUA} ${LUAC} )
288 else ()
289 find_program ( LUAC NAMES luac luac.bat )
290 endif ()
291 endif ( HAVE_LUA_DUMP )
292 message ( "-- bin2c=${BIN2C}" )
293 message ( "-- luac=${LUAC}" )
294
295 get_filename_component ( SOURCEABS ${_source} ABSOLUTE )
296 if ( HAVE_LUA_DUMP )
297 get_filename_component ( SOURCEBASE ${_source} NAME_WE )
298 add_custom_command (
299 OUTPUT ${_target} DEPENDS ${_source}
300 COMMAND ${LUAC} -o ${CMAKE_CURRENT_BINARY_DIR}/${SOURCEBASE}.lo
301 ${SOURCEABS}
302 COMMAND ${BIN2C} ${CMAKE_CURRENT_BINARY_DIR}/${SOURCEBASE}.lo
303 ">${_target}" )
304 else ()
305 add_custom_command (
306 OUTPUT ${_target} DEPENDS ${SOURCEABS}
307 COMMAND ${BIN2C} ${_source} ">${_target}" )
308 endif ()
309endfunction()
diff --git a/dist.info b/dist.info
new file mode 100644
index 0000000..5dfdbaa
--- /dev/null
+++ b/dist.info
@@ -0,0 +1,12 @@
1name = "lua-llthreads2"
2version = "0.1.1"
3
4desc = "A simple Lua wrapper for pthreads & WIN32 threads."
5author = "Alexey Melnichuk"
6license = "MIT/X11"
7url = "https://github.com/moteus/lua-llthreads2"
8maintainer = "Alexey Melnichuk"
9
10depends = {
11 "lua > 5.1"
12} \ No newline at end of file
diff --git a/llthreads2/.gitignore b/llthreads2/.gitignore
new file mode 100644
index 0000000..2122aa6
--- /dev/null
+++ b/llthreads2/.gitignore
@@ -0,0 +1,18 @@
1*.d
2*.spec
3*.obj
4*.dll
5*.o
6*.lib
7*.exp
8*.suo
9*.ncb
10*.user
11*.pdb
12msvc/Debug/
13msvc/Release/
14CMakeCache.txt
15CMakeFiles
16Makefile
17cmake_install.cmake
18install_manifest.txt
diff --git a/llthreads2/.travis.yml b/llthreads2/.travis.yml
new file mode 100644
index 0000000..5b72267
--- /dev/null
+++ b/llthreads2/.travis.yml
@@ -0,0 +1,42 @@
1language: objective-c
2
3env:
4 global:
5 - PLATFORM=macosx
6 - LUAROCKS_VER=2.1.0
7 matrix:
8 - LUA=lua5.1 LUA_SFX=
9 - LUA=lua5.2 LUA_SFX=
10 - LUA=luajit LUA_SFX=jit
11
12branches:
13 only:
14 - master
15
16before_install:
17 - bash .travis/setup_lua.sh
18
19install:
20 - sudo luarocks install lunitx
21 - sudo luarocks make rockspecs/lua-llthreads2-compat-scm-0.rockspec
22 - sudo luarocks make rockspecs/lua-llthreads2-scm-0.rockspec
23
24script:
25 - cd test
26 - lua$LUA_SFX test_table_copy.lua
27 - lua$LUA_SFX test_threads.lua
28 - lua$LUA_SFX test_llthreads.lua
29 # - lua$LUA_SFX test_register_llthreads.lua
30 - lua$LUA_SFX test_join_timeout.lua
31 - lua$LUA_SFX test_join_detach.lua
32 - lua$LUA_SFX test_join_error.lua
33 - lua$LUA_SFX test_register_ffi.lua
34 - lua$LUA_SFX test_logger.lua
35 - lua$LUA_SFX test_pass_cfunction.lua
36 - lua$LUA_SFX test_load_llthreads2.lua
37 - lua$LUA_SFX test_alive.lua
38
39notifications:
40 email:
41 on_success: change
42 on_failure: always
diff --git a/llthreads2/.travis/setup_lua.sh b/llthreads2/.travis/setup_lua.sh
new file mode 100644
index 0000000..47ce49c
--- /dev/null
+++ b/llthreads2/.travis/setup_lua.sh
@@ -0,0 +1,35 @@
1# A script for setting up environment for travis-ci testing.
2# Sets up Lua and Luarocks.
3# LUA must be "lua5.1", "lua5.2" or "luajit".
4# PLATFORM must be "linux" or "macosx".
5
6if [ "$LUA" == "luajit" ]; then
7 curl http://luajit.org/download/LuaJIT-2.0.2.tar.gz | tar xz
8 cd LuaJIT-2.0.2
9 make && sudo make install
10 cd $TRAVIS_BUILD_DIR;
11else
12 if [ "$LUA" == "lua5.1" ]; then
13 curl http://www.lua.org/ftp/lua-5.1.5.tar.gz | tar xz
14 cd lua-5.1.5;
15 elif [ "$LUA" == "lua5.2" ]; then
16 curl http://www.lua.org/ftp/lua-5.2.3.tar.gz | tar xz
17 cd lua-5.2.3;
18 fi
19 sudo make $PLATFORM install
20 cd $TRAVIS_BUILD_DIR;
21fi
22
23LUAROCKS_BASE=luarocks-$LUAROCKS_VER
24curl http://luarocks.org/releases/$LUAROCKS_BASE.tar.gz | tar xz
25cd $LUAROCKS_BASE;
26
27if [ "$LUA" == "luajit" ]; then
28 ./configure --lua-suffix=jit --with-lua-include=/usr/local/include/luajit-2.0;
29else
30 ./configure;
31fi
32
33make && sudo make install
34
35cd $TRAVIS_BUILD_DIR \ No newline at end of file
diff --git a/llthreads2/CMakeLists.txt b/llthreads2/CMakeLists.txt
new file mode 100644
index 0000000..f96b32a
--- /dev/null
+++ b/llthreads2/CMakeLists.txt
@@ -0,0 +1,17 @@
1cmake_minimum_required ( VERSION 2.8 )
2
3project ( lua-llthreads2 C )
4include ( cmake/dist.cmake )
5include ( lua )
6
7set ( CMAKE_THREAD_PREFER_PTHREAD TRUE )
8include ( FindThreads )
9
10include_directories ( ${CMAKE_CURRENT_SOURCE_DIR}/src )
11
12set ( LUA_LLTHREADS_SRC src/l52util.c src/llthread.c )
13
14install_lua_module ( llthreads2 ${LUA_LLTHREADS_SRC} LINK ${CMAKE_THREAD_LIBS_INIT} )
15
16install_data ( COPYRIGHT.llthreads README.md LICENSE )
17install_test ( test/ )
diff --git a/llthreads2/COPYRIGHT.llthreads b/llthreads2/COPYRIGHT.llthreads
new file mode 100644
index 0000000..4826006
--- /dev/null
+++ b/llthreads2/COPYRIGHT.llthreads
@@ -0,0 +1,19 @@
1Copyright (c) 2011 by Robert G. Jakabosky <bobby@sharedrealm.com>
2
3Permission is hereby granted, free of charge, to any person obtaining a copy
4of this software and associated documentation files (the "Software"), to deal
5in the Software without restriction, including without limitation the rights
6to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7copies of the Software, and to permit persons to whom the Software is
8furnished to do so, subject to the following conditions:
9
10The above copyright notice and this permission notice shall be included in
11all copies or substantial portions of the Software.
12
13THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19THE SOFTWARE.
diff --git a/llthreads2/LICENSE b/llthreads2/LICENSE
new file mode 100644
index 0000000..484264b
--- /dev/null
+++ b/llthreads2/LICENSE
@@ -0,0 +1,20 @@
1The MIT License (MIT)
2
3Copyright (c) 2013 Alexey Melnichuk
4
5Permission is hereby granted, free of charge, to any person obtaining a copy of
6this software and associated documentation files (the "Software"), to deal in
7the Software without restriction, including without limitation the rights to
8use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9the Software, and to permit persons to whom the Software is furnished to do so,
10subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in all
13copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/llthreads2/README.md b/llthreads2/README.md
new file mode 100644
index 0000000..22f2025
--- /dev/null
+++ b/llthreads2/README.md
@@ -0,0 +1,113 @@
1lua-llthreads2
2==============
3[![Build Status](https://travis-ci.org/moteus/lua-llthreads2.png?branch=master)](https://travis-ci.org/moteus/lua-llthreads2)
4[![Build Status](https://buildhive.cloudbees.com/job/moteus/job/lua-llthreads2/badge/icon)](https://buildhive.cloudbees.com/job/moteus/job/lua-llthreads2/)
5[![Build Status](https://moteus.ci.cloudbees.com/job/lua-llthreads2/badge/icon)](https://moteus.ci.cloudbees.com/job/lua-llthreads2/)
6
7This is full dropin replacement for [llthreads](https://github.com/Neopallium/lua-llthreads) library.
8
9##Incompatibility list with origin llthreads library
10* does not support Lua 5.0
11* does not support ffi interface (use Lua C API for LuaJIT)
12* returns nil instead of false on error
13* start method returns self instead of true on success
14
15##Additional
16* thread:join() method support zero timeout to check if thread alive (does not work on Windows with pthreads)
17* thread:join() method support arbitrary timeout on Windows threads
18* thread:alive() method return whether the thread is alive (does not work on Windows with pthreads)
19* set_logger function allow logging errors (crash Lua VM) in current llthread's threads
20* thread:start() has additional parameter which control in which thread child Lua VM will be destroyed
21* allow pass cfunctions to child thread (e.g. to initialize Lua state)
22
23##Usage
24
25### Use custom logger
26In this example I use [lua-log](https://github.com/moteus/lua-log) library.
27``` Lua
28-- This is child thread.
29local llthreads = require "llthreads"
30-- Send logs using ZMQ
31local LOG = require"log".new(
32 require "log.writer.net.zmq".new("tcp://127.0.0.1:5555")
33)
34llthread.set_logger(function(msg) LOG.error(msg) end)
35-- This error with traceback will be passed to logger
36error("SOME ERROR")
37```
38
39### Start attached thread collectd in child thread
40``` Lua
41-- This is main thread.
42local thread = require "llthreads".new[[
43 require "utils".sleep(5)
44]]
45
46-- We tell that we start attached thread but child Lua State shuld be close in child thread.
47-- If `thread` became garbage in main thread then finallizer calls thread:join()
48-- and main thread may hungup.
49thread:start(false, false)
50
51-- We can call join.
52-- Because of Lua state destroys in child thread we can not get
53-- returned Lua vaules so we just returns `true`.
54thread:join()
55```
56
57### Start detached joinable thread
58``` Lua
59-- This is main thread.
60local thread = require "llthreads".new[[
61 require "utils".sleep(5)
62]]
63
64-- We tell that we start detached joinable thread. In fact we start attached
65-- thread but if `thread` became garbage in main thread then finallizer just
66-- detach child thread and main thread may not hungup.
67thread:start(true, true)
68
69-- We can call join.
70-- Because of Lua state destroys in child thread we can not get
71-- returned Lua vaules so we just returns `true`.
72thread:join()
73```
74
75### Pass to child thread host application`s library loader
76If you close parent Lua state then some dynamic library may be unloaded
77and cfunction in child Lua state (thread) became invalid.
78
79``` Lua
80-- `myhost.XXX` modules is built-in modules in host application
81-- host application registers cfunction as module loader
82local preload = {}
83preload[ 'myhost.logger' ] = package.preload[ 'myhost.logger' ]
84preload[ 'myhost.config' ] = package.preload[ 'myhost.config' ]
85llthreads.new([[
86 -- registers preload
87 local preload = ...
88 for name, fn in pairs(preload) do package.preload[name] = fn end
89
90 local log = require 'myhost.logger'
91
92]], preload):start(true)
93```
94
95### Wait while thread is alive
96``` Lua
97local thread = require "llthreads".new[[
98 require "utils".sleep(5)
99 return 1
100]]
101thread:start()
102
103-- we can not use `thread:join(0)` because we can not call it twice
104-- so all returned vaules will be lost
105while thread:alive() do
106 -- do some work
107end
108
109local ok, ret = thread:join() -- true, 1
110```
111
112[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/moteus/lua-llthreads2/trend.png)](https://bitdeli.com/free "Bitdeli Badge")
113
diff --git a/llthreads2/cmake/FindLua.cmake b/llthreads2/cmake/FindLua.cmake
new file mode 100644
index 0000000..6991b4a
--- /dev/null
+++ b/llthreads2/cmake/FindLua.cmake
@@ -0,0 +1,127 @@
1# Locate Lua library
2# This module defines
3# LUA_EXECUTABLE, if found
4# LUA_FOUND, if false, do not try to link to Lua
5# LUA_LIBRARIES
6# LUA_INCLUDE_DIR, where to find lua.h
7# LUA_VERSION_STRING, the version of Lua found (since CMake 2.8.8)
8#
9# Note that the expected include convention is
10# #include "lua.h"
11# and not
12# #include <lua/lua.h>
13# This is because, the lua location is not standardized and may exist
14# in locations other than lua/
15
16#=============================================================================
17# Copyright 2007-2009 Kitware, Inc.
18# Modified to support Lua 5.2 by LuaDist 2012
19#
20# Distributed under the OSI-approved BSD License (the "License");
21# see accompanying file Copyright.txt for details.
22#
23# This software is distributed WITHOUT ANY WARRANTY; without even the
24# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
25# See the License for more information.
26#=============================================================================
27# (To distribute this file outside of CMake, substitute the full
28# License text for the above reference.)
29#
30# The required version of Lua can be specified using the
31# standard syntax, e.g. FIND_PACKAGE(Lua 5.1)
32# Otherwise the module will search for any available Lua implementation
33
34# Always search for non-versioned lua first (recommended)
35SET(_POSSIBLE_LUA_INCLUDE include include/lua)
36SET(_POSSIBLE_LUA_EXECUTABLE lua)
37SET(_POSSIBLE_LUA_LIBRARY lua)
38
39# Determine possible naming suffixes (there is no standard for this)
40IF(Lua_FIND_VERSION_MAJOR AND Lua_FIND_VERSION_MINOR)
41 SET(_POSSIBLE_SUFFIXES "${Lua_FIND_VERSION_MAJOR}${Lua_FIND_VERSION_MINOR}" "${Lua_FIND_VERSION_MAJOR}.${Lua_FIND_VERSION_MINOR}" "-${Lua_FIND_VERSION_MAJOR}.${Lua_FIND_VERSION_MINOR}")
42ELSE(Lua_FIND_VERSION_MAJOR AND Lua_FIND_VERSION_MINOR)
43 SET(_POSSIBLE_SUFFIXES "52" "5.2" "-5.2" "51" "5.1" "-5.1")
44ENDIF(Lua_FIND_VERSION_MAJOR AND Lua_FIND_VERSION_MINOR)
45
46# Set up possible search names and locations
47FOREACH(_SUFFIX ${_POSSIBLE_SUFFIXES})
48 LIST(APPEND _POSSIBLE_LUA_INCLUDE "include/lua${_SUFFIX}")
49 LIST(APPEND _POSSIBLE_LUA_EXECUTABLE "lua${_SUFFIX}")
50 LIST(APPEND _POSSIBLE_LUA_LIBRARY "lua${_SUFFIX}")
51ENDFOREACH(_SUFFIX)
52
53# Find the lua executable
54FIND_PROGRAM(LUA_EXECUTABLE
55 NAMES ${_POSSIBLE_LUA_EXECUTABLE}
56)
57
58# Find the lua header
59FIND_PATH(LUA_INCLUDE_DIR lua.h
60 HINTS
61 $ENV{LUA_DIR}
62 PATH_SUFFIXES ${_POSSIBLE_LUA_INCLUDE}
63 PATHS
64 ~/Library/Frameworks
65 /Library/Frameworks
66 /usr/local
67 /usr
68 /sw # Fink
69 /opt/local # DarwinPorts
70 /opt/csw # Blastwave
71 /opt
72)
73
74# Find the lua library
75FIND_LIBRARY(LUA_LIBRARY
76 NAMES ${_POSSIBLE_LUA_LIBRARY}
77 HINTS
78 $ENV{LUA_DIR}
79 PATH_SUFFIXES lib64 lib
80 PATHS
81 ~/Library/Frameworks
82 /Library/Frameworks
83 /usr/local
84 /usr
85 /sw
86 /opt/local
87 /opt/csw
88 /opt
89)
90
91IF(LUA_LIBRARY)
92 # include the math library for Unix
93 IF(UNIX AND NOT APPLE)
94 FIND_LIBRARY(LUA_MATH_LIBRARY m)
95 SET( LUA_LIBRARIES "${LUA_LIBRARY};${LUA_MATH_LIBRARY}" CACHE STRING "Lua Libraries")
96 # For Windows and Mac, don't need to explicitly include the math library
97 ELSE(UNIX AND NOT APPLE)
98 SET( LUA_LIBRARIES "${LUA_LIBRARY}" CACHE STRING "Lua Libraries")
99 ENDIF(UNIX AND NOT APPLE)
100ENDIF(LUA_LIBRARY)
101
102# Determine Lua version
103IF(LUA_INCLUDE_DIR AND EXISTS "${LUA_INCLUDE_DIR}/lua.h")
104 FILE(STRINGS "${LUA_INCLUDE_DIR}/lua.h" lua_version_str REGEX "^#define[ \t]+LUA_RELEASE[ \t]+\"Lua .+\"")
105
106 STRING(REGEX REPLACE "^#define[ \t]+LUA_RELEASE[ \t]+\"Lua ([^\"]+)\".*" "\\1" LUA_VERSION_STRING "${lua_version_str}")
107 UNSET(lua_version_str)
108ENDIF()
109
110# Lua 5.2
111IF(NOT LUA_VERSION_STRING)
112 FILE(STRINGS "${LUA_INCLUDE_DIR}/lua.h" lua_version_str REGEX "^#define LUA_VERSION_[A-Z]+[ \t]+\"[0-9]+\"")
113 STRING(REGEX REPLACE ".*#define LUA_VERSION_MAJOR[ \t]+\"([0-9]+)\".*" "\\1" LUA_VERSION_MAJOR ${lua_version_str})
114 STRING(REGEX REPLACE ".*#define LUA_VERSION_MINOR[ \t]+\"([0-9]+)\".*" "\\1" LUA_VERSION_MINOR ${lua_version_str})
115 STRING(REGEX REPLACE ".*#define LUA_VERSION_RELEASE[ \t]+\"([0-9]+)\".*" "\\1" LUA_VERSION_RELEASE ${lua_version_str})
116 SET(LUA_VERSION_STRING ${LUA_VERSION_MAJOR}.${LUA_VERSION_MINOR}.${LUA_VERSION_RELEASE})
117ENDIF()
118
119INCLUDE(FindPackageHandleStandardArgs)
120# handle the QUIETLY and REQUIRED arguments and set LUA_FOUND to TRUE if
121# all listed variables are TRUE
122FIND_PACKAGE_HANDLE_STANDARD_ARGS(Lua
123 REQUIRED_VARS LUA_LIBRARIES LUA_INCLUDE_DIR
124 VERSION_VAR LUA_VERSION_STRING)
125
126MARK_AS_ADVANCED(LUA_INCLUDE_DIR LUA_LIBRARIES LUA_LIBRARY LUA_MATH_LIBRARY LUA_EXECUTABLE)
127
diff --git a/llthreads2/cmake/dist.cmake b/llthreads2/cmake/dist.cmake
new file mode 100644
index 0000000..310ef94
--- /dev/null
+++ b/llthreads2/cmake/dist.cmake
@@ -0,0 +1,321 @@
1# LuaDist CMake utility library.
2# Provides sane project defaults and macros common to LuaDist CMake builds.
3#
4# Copyright (C) 2007-2012 LuaDist.
5# by David Manura, Peter Drahoš
6# Redistribution and use of this file is allowed according to the terms of the MIT license.
7# For details see the COPYRIGHT file distributed with LuaDist.
8# Please note that the package source code is licensed under its own license.
9
10## Extract information from dist.info
11if ( NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/dist.info )
12 message ( FATAL_ERROR
13 "Missing dist.info file (${CMAKE_CURRENT_SOURCE_DIR}/dist.info)." )
14endif ()
15file ( READ ${CMAKE_CURRENT_SOURCE_DIR}/dist.info DIST_INFO )
16if ( "${DIST_INFO}" STREQUAL "" )
17 message ( FATAL_ERROR "Failed to load dist.info." )
18endif ()
19# Reads field `name` from dist.info string `DIST_INFO` into variable `var`.
20macro ( _parse_dist_field name var )
21 string ( REGEX REPLACE ".*${name}[ \t]?=[ \t]?[\"']([^\"']+)[\"'].*" "\\1"
22 ${var} "${DIST_INFO}" )
23 if ( ${var} STREQUAL DIST_INFO )
24 message ( FATAL_ERROR "Failed to extract \"${var}\" from dist.info" )
25 endif ()
26endmacro ()
27#
28_parse_dist_field ( name DIST_NAME )
29_parse_dist_field ( version DIST_VERSION )
30_parse_dist_field ( license DIST_LICENSE )
31_parse_dist_field ( author DIST_AUTHOR )
32_parse_dist_field ( maintainer DIST_MAINTAINER )
33_parse_dist_field ( url DIST_URL )
34_parse_dist_field ( desc DIST_DESC )
35message ( "DIST_NAME: ${DIST_NAME}")
36message ( "DIST_VERSION: ${DIST_VERSION}")
37message ( "DIST_LICENSE: ${DIST_LICENSE}")
38message ( "DIST_AUTHOR: ${DIST_AUTHOR}")
39message ( "DIST_MAINTAINER: ${DIST_MAINTAINER}")
40message ( "DIST_URL: ${DIST_URL}")
41message ( "DIST_DESC: ${DIST_DESC}")
42string ( REGEX REPLACE ".*depends[ \t]?=[ \t]?[\"']([^\"']+)[\"'].*" "\\1"
43 DIST_DEPENDS ${DIST_INFO} )
44if ( DIST_DEPENDS STREQUAL DIST_INFO )
45 set ( DIST_DEPENDS "" )
46endif ()
47message ( "DIST_DEPENDS: ${DIST_DEPENDS}")
48## 2DO: Parse DIST_DEPENDS and try to install Dependencies with automatically using externalproject_add
49
50
51## INSTALL DEFAULTS (Relative to CMAKE_INSTALL_PREFIX)
52# Primary paths
53set ( INSTALL_BIN bin CACHE PATH "Where to install binaries to." )
54set ( INSTALL_LIB lib CACHE PATH "Where to install libraries to." )
55set ( INSTALL_INC include CACHE PATH "Where to install headers to." )
56set ( INSTALL_ETC etc CACHE PATH "Where to store configuration files" )
57set ( INSTALL_SHARE share CACHE PATH "Directory for shared data." )
58
59# Secondary paths
60option ( INSTALL_VERSION
61 "Install runtime libraries and executables with version information." OFF)
62set ( INSTALL_DATA ${INSTALL_SHARE}/${DIST_NAME} CACHE PATH
63 "Directory the package can store documentation, tests or other data in.")
64set ( INSTALL_DOC ${INSTALL_DATA}/doc CACHE PATH
65 "Recommended directory to install documentation into.")
66set ( INSTALL_EXAMPLE ${INSTALL_DATA}/example CACHE PATH
67 "Recommended directory to install examples into.")
68set ( INSTALL_TEST ${INSTALL_DATA}/test CACHE PATH
69 "Recommended directory to install tests into.")
70set ( INSTALL_FOO ${INSTALL_DATA}/etc CACHE PATH
71 "Where to install additional files")
72
73# Tweaks and other defaults
74# Setting CMAKE to use loose block and search for find modules in source directory
75set ( CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS true )
76set ( CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH} )
77option ( BUILD_SHARED_LIBS "Build shared libraries" ON )
78
79# In MSVC, prevent warnings that can occur when using standard libraries.
80if ( MSVC )
81 add_definitions ( -D_CRT_SECURE_NO_WARNINGS )
82endif ()
83
84# RPath and relative linking
85option ( USE_RPATH "Use relative linking." ON)
86if ( USE_RPATH )
87 string ( REGEX REPLACE "[^!/]+" ".." UP_DIR ${INSTALL_BIN} )
88 set ( CMAKE_SKIP_BUILD_RPATH FALSE CACHE STRING "" FORCE )
89 set ( CMAKE_BUILD_WITH_INSTALL_RPATH FALSE CACHE STRING "" FORCE )
90 set ( CMAKE_INSTALL_RPATH $ORIGIN/${UP_DIR}/${INSTALL_LIB}
91 CACHE STRING "" FORCE )
92 set ( CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE CACHE STRING "" FORCE )
93 set ( CMAKE_INSTALL_NAME_DIR @executable_path/${UP_DIR}/${INSTALL_LIB}
94 CACHE STRING "" FORCE )
95endif ()
96
97## MACROS
98# Parser macro
99macro ( parse_arguments prefix arg_names option_names)
100 set ( DEFAULT_ARGS )
101 foreach ( arg_name ${arg_names} )
102 set ( ${prefix}_${arg_name} )
103 endforeach ()
104 foreach ( option ${option_names} )
105 set ( ${prefix}_${option} FALSE )
106 endforeach ()
107
108 set ( current_arg_name DEFAULT_ARGS )
109 set ( current_arg_list )
110 foreach ( arg ${ARGN} )
111 set ( larg_names ${arg_names} )
112 list ( FIND larg_names "${arg}" is_arg_name )
113 if ( is_arg_name GREATER -1 )
114 set ( ${prefix}_${current_arg_name} ${current_arg_list} )
115 set ( current_arg_name ${arg} )
116 set ( current_arg_list )
117 else ()
118 set ( loption_names ${option_names} )
119 list ( FIND loption_names "${arg}" is_option )
120 if ( is_option GREATER -1 )
121 set ( ${prefix}_${arg} TRUE )
122 else ()
123 set ( current_arg_list ${current_arg_list} ${arg} )
124 endif ()
125 endif ()
126 endforeach ()
127 set ( ${prefix}_${current_arg_name} ${current_arg_list} )
128endmacro ()
129
130
131# install_executable ( executable_targets )
132# Installs any executables generated using "add_executable".
133# USE: install_executable ( lua )
134# NOTE: subdirectories are NOT supported
135set ( CPACK_COMPONENT_RUNTIME_DISPLAY_NAME "${DIST_NAME} Runtime" )
136set ( CPACK_COMPONENT_RUNTIME_DESCRIPTION
137 "Executables and runtime libraries. Installed into ${INSTALL_BIN}." )
138macro ( install_executable )
139 foreach ( _file ${ARGN} )
140 if ( INSTALL_VERSION )
141 set_target_properties ( ${_file} PROPERTIES VERSION ${DIST_VERSION}
142 SOVERSION ${DIST_VERSION} )
143 endif ()
144 install ( TARGETS ${_file} RUNTIME DESTINATION ${INSTALL_BIN}
145 COMPONENT Runtime )
146 endforeach()
147endmacro ()
148
149# install_library ( library_targets )
150# Installs any libraries generated using "add_library" into apropriate places.
151# USE: install_library ( libexpat )
152# NOTE: subdirectories are NOT supported
153set ( CPACK_COMPONENT_LIBRARY_DISPLAY_NAME "${DIST_NAME} Development Libraries" )
154set ( CPACK_COMPONENT_LIBRARY_DESCRIPTION
155 "Static and import libraries needed for development. Installed into ${INSTALL_LIB} or ${INSTALL_BIN}." )
156macro ( install_library )
157 foreach ( _file ${ARGN} )
158 if ( INSTALL_VERSION )
159 set_target_properties ( ${_file} PROPERTIES VERSION ${DIST_VERSION}
160 SOVERSION ${DIST_VERSION} )
161 endif ()
162 install ( TARGETS ${_file}
163 RUNTIME DESTINATION ${INSTALL_BIN} COMPONENT Runtime
164 LIBRARY DESTINATION ${INSTALL_LIB} COMPONENT Runtime
165 ARCHIVE DESTINATION ${INSTALL_LIB} COMPONENT Library )
166 endforeach()
167endmacro ()
168
169# helper function for various install_* functions, for PATTERN/REGEX args.
170macro ( _complete_install_args )
171 if ( NOT("${_ARG_PATTERN}" STREQUAL "") )
172 set ( _ARG_PATTERN PATTERN ${_ARG_PATTERN} )
173 endif ()
174 if ( NOT("${_ARG_REGEX}" STREQUAL "") )
175 set ( _ARG_REGEX REGEX ${_ARG_REGEX} )
176 endif ()
177endmacro ()
178
179# install_header ( files/directories [INTO destination] )
180# Install a directories or files into header destination.
181# USE: install_header ( lua.h luaconf.h ) or install_header ( GL )
182# USE: install_header ( mylib.h INTO mylib )
183# For directories, supports optional PATTERN/REGEX arguments like install().
184set ( CPACK_COMPONENT_HEADER_DISPLAY_NAME "${DIST_NAME} Development Headers" )
185set ( CPACK_COMPONENT_HEADER_DESCRIPTION
186 "Headers needed for development. Installed into ${INSTALL_INC}." )
187macro ( install_header )
188 parse_arguments ( _ARG "INTO;PATTERN;REGEX" "" ${ARGN} )
189 _complete_install_args()
190 foreach ( _file ${_ARG_DEFAULT_ARGS} )
191 if ( IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/${_file}" )
192 install ( DIRECTORY ${_file} DESTINATION ${INSTALL_INC}/${_ARG_INTO}
193 COMPONENT Header ${_ARG_PATTERN} ${_ARG_REGEX} )
194 else ()
195 install ( FILES ${_file} DESTINATION ${INSTALL_INC}/${_ARG_INTO}
196 COMPONENT Header )
197 endif ()
198 endforeach()
199endmacro ()
200
201# install_data ( files/directories [INTO destination] )
202# This installs additional data files or directories.
203# USE: install_data ( extra data.dat )
204# USE: install_data ( image1.png image2.png INTO images )
205# For directories, supports optional PATTERN/REGEX arguments like install().
206set ( CPACK_COMPONENT_DATA_DISPLAY_NAME "${DIST_NAME} Data" )
207set ( CPACK_COMPONENT_DATA_DESCRIPTION
208 "Application data. Installed into ${INSTALL_DATA}." )
209macro ( install_data )
210 parse_arguments ( _ARG "INTO;PATTERN;REGEX" "" ${ARGN} )
211 _complete_install_args()
212 foreach ( _file ${_ARG_DEFAULT_ARGS} )
213 if ( IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/${_file}" )
214 install ( DIRECTORY ${_file}
215 DESTINATION ${INSTALL_DATA}/${_ARG_INTO}
216 COMPONENT Data ${_ARG_PATTERN} ${_ARG_REGEX} )
217 else ()
218 install ( FILES ${_file} DESTINATION ${INSTALL_DATA}/${_ARG_INTO}
219 COMPONENT Data )
220 endif ()
221 endforeach()
222endmacro ()
223
224# INSTALL_DOC ( files/directories [INTO destination] )
225# This installs documentation content
226# USE: install_doc ( doc/ doc.pdf )
227# USE: install_doc ( index.html INTO html )
228# For directories, supports optional PATTERN/REGEX arguments like install().
229set ( CPACK_COMPONENT_DOCUMENTATION_DISPLAY_NAME "${DIST_NAME} Documentation" )
230set ( CPACK_COMPONENT_DOCUMENTATION_DESCRIPTION
231 "Application documentation. Installed into ${INSTALL_DOC}." )
232macro ( install_doc )
233 parse_arguments ( _ARG "INTO;PATTERN;REGEX" "" ${ARGN} )
234 _complete_install_args()
235 foreach ( _file ${_ARG_DEFAULT_ARGS} )
236 if ( IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/${_file}" )
237 install ( DIRECTORY ${_file} DESTINATION ${INSTALL_DOC}/${_ARG_INTO}
238 COMPONENT Documentation ${_ARG_PATTERN} ${_ARG_REGEX} )
239 else ()
240 install ( FILES ${_file} DESTINATION ${INSTALL_DOC}/${_ARG_INTO}
241 COMPONENT Documentation )
242 endif ()
243 endforeach()
244endmacro ()
245
246# install_example ( files/directories [INTO destination] )
247# This installs additional examples
248# USE: install_example ( examples/ exampleA )
249# USE: install_example ( super_example super_data INTO super)
250# For directories, supports optional PATTERN/REGEX argument like install().
251set ( CPACK_COMPONENT_EXAMPLE_DISPLAY_NAME "${DIST_NAME} Examples" )
252set ( CPACK_COMPONENT_EXAMPLE_DESCRIPTION
253 "Examples and their associated data. Installed into ${INSTALL_EXAMPLE}." )
254macro ( install_example )
255 parse_arguments ( _ARG "INTO;PATTERN;REGEX" "" ${ARGN} )
256 _complete_install_args()
257 foreach ( _file ${_ARG_DEFAULT_ARGS} )
258 if ( IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/${_file}" )
259 install ( DIRECTORY ${_file} DESTINATION ${INSTALL_EXAMPLE}/${_ARG_INTO}
260 COMPONENT Example ${_ARG_PATTERN} ${_ARG_REGEX} )
261 else ()
262 install ( FILES ${_file} DESTINATION ${INSTALL_EXAMPLE}/${_ARG_INTO}
263 COMPONENT Example )
264 endif ()
265 endforeach()
266endmacro ()
267
268# install_test ( files/directories [INTO destination] )
269# This installs tests and test files, DOES NOT EXECUTE TESTS
270# USE: install_test ( my_test data.sql )
271# USE: install_test ( feature_x_test INTO x )
272# For directories, supports optional PATTERN/REGEX argument like install().
273set ( CPACK_COMPONENT_TEST_DISPLAY_NAME "${DIST_NAME} Tests" )
274set ( CPACK_COMPONENT_TEST_DESCRIPTION
275 "Tests and associated data. Installed into ${INSTALL_TEST}." )
276macro ( install_test )
277 parse_arguments ( _ARG "INTO;PATTERN;REGEX" "" ${ARGN} )
278 _complete_install_args()
279 foreach ( _file ${_ARG_DEFAULT_ARGS} )
280 if ( IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/${_file}" )
281 install ( DIRECTORY ${_file} DESTINATION ${INSTALL_TEST}/${_ARG_INTO}
282 COMPONENT Test ${_ARG_PATTERN} ${_ARG_REGEX} )
283 else ()
284 install ( FILES ${_file} DESTINATION ${INSTALL_TEST}/${_ARG_INTO}
285 COMPONENT Test )
286 endif ()
287 endforeach()
288endmacro ()
289
290# install_foo ( files/directories [INTO destination] )
291# This installs optional or otherwise unneeded content
292# USE: install_foo ( etc/ example.doc )
293# USE: install_foo ( icon.png logo.png INTO icons)
294# For directories, supports optional PATTERN/REGEX argument like install().
295set ( CPACK_COMPONENT_OTHER_DISPLAY_NAME "${DIST_NAME} Unspecified Content" )
296set ( CPACK_COMPONENT_OTHER_DESCRIPTION
297 "Other unspecified content. Installed into ${INSTALL_FOO}." )
298macro ( install_foo )
299 parse_arguments ( _ARG "INTO;PATTERN;REGEX" "" ${ARGN} )
300 _complete_install_args()
301 foreach ( _file ${_ARG_DEFAULT_ARGS} )
302 if ( IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/${_file}" )
303 install ( DIRECTORY ${_file} DESTINATION ${INSTALL_FOO}/${_ARG_INTO}
304 COMPONENT Other ${_ARG_PATTERN} ${_ARG_REGEX} )
305 else ()
306 install ( FILES ${_file} DESTINATION ${INSTALL_FOO}/${_ARG_INTO}
307 COMPONENT Other )
308 endif ()
309 endforeach()
310endmacro ()
311
312## CTest defaults
313
314## CPack defaults
315set ( CPACK_GENERATOR "ZIP" )
316set ( CPACK_STRIP_FILES TRUE )
317set ( CPACK_PACKAGE_NAME "${DIST_NAME}" )
318set ( CPACK_PACKAGE_VERSION "${DIST_VERSION}")
319set ( CPACK_PACKAGE_VENDOR "LuaDist" )
320set ( CPACK_COMPONENTS_ALL Runtime Library Header Data Documentation Example Other )
321include ( CPack )
diff --git a/llthreads2/cmake/lua.cmake b/llthreads2/cmake/lua.cmake
new file mode 100644
index 0000000..ee2e35d
--- /dev/null
+++ b/llthreads2/cmake/lua.cmake
@@ -0,0 +1,309 @@
1# LuaDist CMake utility library for Lua.
2#
3# Copyright (C) 2007-2012 LuaDist.
4# by David Manura, Peter Drahos
5# Redistribution and use of this file is allowed according to the terms of the MIT license.
6# For details see the COPYRIGHT file distributed with LuaDist.
7# Please note that the package source code is licensed under its own license.
8
9set ( INSTALL_LMOD ${INSTALL_LIB}/lua
10 CACHE PATH "Directory to install Lua modules." )
11set ( INSTALL_CMOD ${INSTALL_LIB}/lua
12 CACHE PATH "Directory to install Lua binary modules." )
13
14option ( LUA_SKIP_WRAPPER
15 "Do not build and install Lua executable wrappers." OFF )
16option ( LUA_STATIC_MODULE "Build modules for static linking" OFF )
17
18# List of (Lua module name, file path) pairs.
19# Used internally by add_lua_test. Built by add_lua_module.
20set ( _lua_modules )
21
22# utility function: appends path `path` to path `basepath`, properly
23# handling cases when `path` may be relative or absolute.
24macro ( _append_path basepath path result )
25 if ( IS_ABSOLUTE "${path}" )
26 set ( ${result} "${path}" )
27 else ()
28 set ( ${result} "${basepath}/${path}" )
29 endif ()
30endmacro ()
31
32# install_lua_executable ( target source )
33# Automatically generate a binary if srlua package is available
34# The application or its source will be placed into /bin
35# If the application source did not have .lua suffix then it will be added
36# USE: lua_executable ( sputnik src/sputnik.lua )
37macro ( install_lua_executable _name _source )
38 get_filename_component ( _source_name ${_source} NAME_WE )
39 # Find srlua and glue
40 find_program( SRLUA_EXECUTABLE NAMES srlua )
41 find_program( GLUE_EXECUTABLE NAMES glue )
42 # Executable output
43 set ( _exe ${CMAKE_CURRENT_BINARY_DIR}/${_name}${CMAKE_EXECUTABLE_SUFFIX} )
44 if ( NOT SKIP_LUA_WRAPPER AND SRLUA_EXECUTABLE AND GLUE_EXECUTABLE )
45 # Generate binary gluing the lua code to srlua, this is a robuust approach for most systems
46 add_custom_command(
47 OUTPUT ${_exe}
48 COMMAND ${GLUE_EXECUTABLE}
49 ARGS ${SRLUA_EXECUTABLE} ${_source} ${_exe}
50 DEPENDS ${_source}
51 WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
52 VERBATIM
53 )
54 # Make sure we have a target associated with the binary
55 add_custom_target(${_name} ALL
56 DEPENDS ${_exe}
57 )
58 # Install with run permissions
59 install ( PROGRAMS ${_exe} DESTINATION ${INSTALL_BIN} COMPONENT Runtime)
60 # Also install source as optional resurce
61 install ( FILES ${_source} DESTINATION ${INSTALL_FOO} COMPONENT Other )
62 else()
63 # Install into bin as is but without the lua suffix, we assume the executable uses UNIX shebang/hash-bang magic
64 install ( PROGRAMS ${_source} DESTINATION ${INSTALL_BIN}
65 RENAME ${_source_name}
66 COMPONENT Runtime
67 )
68 endif()
69endmacro ()
70
71macro ( _lua_module_helper is_install _name )
72 parse_arguments ( _MODULE "LINK;ALL_IN_ONE" "" ${ARGN} )
73 # _target is CMake-compatible target name for module (e.g. socket_core).
74 # _module is relative path of target (e.g. socket/core),
75 # without extension (e.g. .lua/.so/.dll).
76 # _MODULE_SRC is list of module source files (e.g. .lua and .c files).
77 # _MODULE_NAMES is list of module names (e.g. socket.core).
78 if ( _MODULE_ALL_IN_ONE )
79 string ( REGEX REPLACE "\\..*" "" _target "${_name}" )
80 string ( REGEX REPLACE "\\..*" "" _module "${_name}" )
81 set ( _target "${_target}_all_in_one")
82 set ( _MODULE_SRC ${_MODULE_ALL_IN_ONE} )
83 set ( _MODULE_NAMES ${_name} ${_MODULE_DEFAULT_ARGS} )
84 else ()
85 string ( REPLACE "." "_" _target "${_name}" )
86 string ( REPLACE "." "/" _module "${_name}" )
87 set ( _MODULE_SRC ${_MODULE_DEFAULT_ARGS} )
88 set ( _MODULE_NAMES ${_name} )
89 endif ()
90 if ( NOT _MODULE_SRC )
91 message ( FATAL_ERROR "no module sources specified" )
92 endif ()
93 list ( GET _MODULE_SRC 0 _first_source )
94
95 get_filename_component ( _ext ${_first_source} EXT )
96 if ( _ext STREQUAL ".lua" ) # Lua source module
97 list ( LENGTH _MODULE_SRC _len )
98 if ( _len GREATER 1 )
99 message ( FATAL_ERROR "more than one source file specified" )
100 endif ()
101
102 set ( _module "${_module}.lua" )
103
104 get_filename_component ( _module_dir ${_module} PATH )
105 get_filename_component ( _module_filename ${_module} NAME )
106 _append_path ( "${CMAKE_CURRENT_SOURCE_DIR}" "${_first_source}" _module_path )
107 list ( APPEND _lua_modules "${_name}" "${_module_path}" )
108
109 if ( ${is_install} )
110 install ( FILES ${_first_source} DESTINATION ${INSTALL_LMOD}/${_module_dir}
111 RENAME ${_module_filename}
112 COMPONENT Runtime
113 )
114 endif ()
115 else () # Lua C binary module
116 enable_language ( C )
117 find_package ( Lua REQUIRED )
118 include_directories ( ${LUA_INCLUDE_DIR} )
119
120 set ( _module "${_module}${CMAKE_SHARED_MODULE_SUFFIX}" )
121
122 get_filename_component ( _module_dir ${_module} PATH )
123 get_filename_component ( _module_filenamebase ${_module} NAME_WE )
124 foreach ( _thisname ${_MODULE_NAMES} )
125 list ( APPEND _lua_modules "${_thisname}"
126 "${CMAKE_CURRENT_BINARY_DIR}/\${CMAKE_CFG_INTDIR}/${_module}" )
127 endforeach ()
128
129 # Static module (not linking to lua)
130 if ( LUA_STATIC_MODULE )
131 add_library( ${_target} STATIC ${_MODULE_SRC})
132 target_link_libraries ( ${_target} ${_MODULE_LINK} )
133 else ()
134 # Dynamic module
135 add_library( ${_target} MODULE ${_MODULE_SRC})
136 target_link_libraries ( ${_target} ${LUA_LIBRARY} ${_MODULE_LINK} )
137 endif ()
138
139 set_target_properties ( ${_target} PROPERTIES
140 ARCHIVE_OUTPUT_DIRECTORY "${_module_dir}"
141 LIBRARY_OUTPUT_DIRECTORY "${_module_dir}"
142 PREFIX ""
143 OUTPUT_NAME "${_module_filenamebase}" )
144 if ( ${is_install} )
145 install ( TARGETS ${_target}
146 LIBRARY DESTINATION ${INSTALL_CMOD}/${_module_dir}
147 COMPONENT Runtime
148 ARCHIVE DESTINATION ${INSTALL_CMOD}/${_module_dir}
149 COMPONENT Library )
150 endif ()
151 endif ()
152endmacro ()
153
154# add_lua_module
155# Builds a Lua source module into a destination locatable by Lua
156# require syntax.
157# Binary modules are also supported where this function takes sources and
158# libraries to compile separated by LINK keyword.
159# USE: add_lua_module ( socket.http src/http.lua )
160# USE2: add_lua_module ( mime.core src/mime.c )
161# USE3: add_lua_module ( socket.core ${SRC_SOCKET} LINK ${LIB_SOCKET} )
162# USE4: add_lua_module ( ssl.context ssl.core ALL_IN_ONE src/context.c src/ssl.c )
163# This form builds an "all-in-one" module (e.g. ssl.so or ssl.dll containing
164# both modules ssl.context and ssl.core). The CMake target name will be
165# ssl_all_in_one.
166# Also sets variable _module_path (relative path where module typically
167# would be installed).
168macro ( add_lua_module )
169 _lua_module_helper ( 0 ${ARGN} )
170endmacro ()
171
172
173# install_lua_module
174# This is the same as `add_lua_module` but also installs the module.
175# USE: install_lua_module ( socket.http src/http.lua )
176# USE2: install_lua_module ( mime.core src/mime.c )
177# USE3: install_lua_module ( socket.core ${SRC_SOCKET} LINK ${LIB_SOCKET} )
178macro ( install_lua_module )
179 _lua_module_helper ( 1 ${ARGN} )
180endmacro ()
181
182# Builds string representing Lua table mapping Lua modules names to file
183# paths. Used internally.
184macro ( _make_module_table _outvar )
185 set ( ${_outvar} )
186 list ( LENGTH _lua_modules _n )
187 if ( ${_n} GREATER 0 ) # avoids cmake complaint
188 foreach ( _i RANGE 1 ${_n} 2 )
189 list ( GET _lua_modules ${_i} _path )
190 math ( EXPR _ii ${_i}-1 )
191 list ( GET _lua_modules ${_ii} _name )
192 set ( ${_outvar} "${_table} ['${_name}'] = '${_path}'\;\n")
193 endforeach ()
194 endif ()
195 set ( ${_outvar}
196"local modules = {
197${_table}}" )
198endmacro ()
199
200# add_lua_test ( _testfile [ WORKING_DIRECTORY _working_dir ] )
201# Runs Lua script `_testfile` under CTest tester.
202# Optional named argument `WORKING_DIRECTORY` is current working directory to
203# run test under (defaults to ${CMAKE_CURRENT_BINARY_DIR}).
204# Both paths, if relative, are relative to ${CMAKE_CURRENT_SOURCE_DIR}.
205# Any modules previously defined with install_lua_module are automatically
206# preloaded (via package.preload) prior to running the test script.
207# Under LuaDist, set test=true in config.lua to enable testing.
208# USE: add_lua_test ( test/test1.lua [args...] [WORKING_DIRECTORY dir])
209macro ( add_lua_test _testfile )
210 if ( NOT SKIP_TESTING )
211 parse_arguments ( _ARG "WORKING_DIRECTORY" "" ${ARGN} )
212 include ( CTest )
213 find_program ( LUA NAMES lua lua.bat )
214 get_filename_component ( TESTFILEABS ${_testfile} ABSOLUTE )
215 get_filename_component ( TESTFILENAME ${_testfile} NAME )
216 get_filename_component ( TESTFILEBASE ${_testfile} NAME_WE )
217
218 # Write wrapper script.
219 # Note: One simple way to allow the script to find modules is
220 # to just put them in package.preload.
221 set ( TESTWRAPPER ${CMAKE_CURRENT_BINARY_DIR}/${TESTFILENAME} )
222 _make_module_table ( _table )
223 set ( TESTWRAPPERSOURCE
224"local CMAKE_CFG_INTDIR = ... or '.'
225${_table}
226local function preload_modules(modules)
227 for name, path in pairs(modules) do
228 if path:match'%.lua' then
229 package.preload[name] = assert(loadfile(path))
230 else
231 local name = name:gsub('.*%-', '') -- remove any hyphen prefix
232 local symbol = 'luaopen_' .. name:gsub('%.', '_')
233 --improve: generalize to support all-in-one loader?
234 local path = path:gsub('%$%{CMAKE_CFG_INTDIR%}', CMAKE_CFG_INTDIR)
235 package.preload[name] = assert(package.loadlib(path, symbol))
236 end
237 end
238end
239preload_modules(modules)
240arg[0] = '${TESTFILEABS}'
241table.remove(arg, 1)
242return assert(loadfile '${TESTFILEABS}')(unpack(arg))
243" )
244 if ( _ARG_WORKING_DIRECTORY )
245 get_filename_component (
246 TESTCURRENTDIRABS ${_ARG_WORKING_DIRECTORY} ABSOLUTE )
247 # note: CMake 2.6 (unlike 2.8) lacks WORKING_DIRECTORY parameter.
248 set ( _pre ${CMAKE_COMMAND} -E chdir "${TESTCURRENTDIRABS}" )
249 endif ()
250 file ( WRITE ${TESTWRAPPER} ${TESTWRAPPERSOURCE})
251 add_test ( NAME ${TESTFILEBASE} COMMAND ${_pre} ${LUA}
252 ${TESTWRAPPER} "${CMAKE_CFG_INTDIR}"
253 ${_ARG_DEFAULT_ARGS} )
254 endif ()
255 # see also http://gdcm.svn.sourceforge.net/viewvc/gdcm/Sandbox/CMakeModules/UsePythonTest.cmake
256 # Note: ${CMAKE_CFG_INTDIR} is a command-line argument to allow proper
257 # expansion by the native build tool.
258endmacro ()
259
260
261# Converts Lua source file `_source` to binary string embedded in C source
262# file `_target`. Optionally compiles Lua source to byte code (not available
263# under LuaJIT2, which doesn't have a bytecode loader). Additionally, Lua
264# versions of bin2c [1] and luac [2] may be passed respectively as additional
265# arguments.
266#
267# [1] http://lua-users.org/wiki/BinToCee
268# [2] http://lua-users.org/wiki/LuaCompilerInLua
269function ( add_lua_bin2c _target _source )
270 find_program ( LUA NAMES lua lua.bat )
271 execute_process ( COMMAND ${LUA} -e "string.dump(function()end)"
272 RESULT_VARIABLE _LUA_DUMP_RESULT ERROR_QUIET )
273 if ( NOT ${_LUA_DUMP_RESULT} )
274 SET ( HAVE_LUA_DUMP true )
275 endif ()
276 message ( "-- string.dump=${HAVE_LUA_DUMP}" )
277
278 if ( ARGV2 )
279 get_filename_component ( BIN2C ${ARGV2} ABSOLUTE )
280 set ( BIN2C ${LUA} ${BIN2C} )
281 else ()
282 find_program ( BIN2C NAMES bin2c bin2c.bat )
283 endif ()
284 if ( HAVE_LUA_DUMP )
285 if ( ARGV3 )
286 get_filename_component ( LUAC ${ARGV3} ABSOLUTE )
287 set ( LUAC ${LUA} ${LUAC} )
288 else ()
289 find_program ( LUAC NAMES luac luac.bat )
290 endif ()
291 endif ( HAVE_LUA_DUMP )
292 message ( "-- bin2c=${BIN2C}" )
293 message ( "-- luac=${LUAC}" )
294
295 get_filename_component ( SOURCEABS ${_source} ABSOLUTE )
296 if ( HAVE_LUA_DUMP )
297 get_filename_component ( SOURCEBASE ${_source} NAME_WE )
298 add_custom_command (
299 OUTPUT ${_target} DEPENDS ${_source}
300 COMMAND ${LUAC} -o ${CMAKE_CURRENT_BINARY_DIR}/${SOURCEBASE}.lo
301 ${SOURCEABS}
302 COMMAND ${BIN2C} ${CMAKE_CURRENT_BINARY_DIR}/${SOURCEBASE}.lo
303 ">${_target}" )
304 else ()
305 add_custom_command (
306 OUTPUT ${_target} DEPENDS ${SOURCEABS}
307 COMMAND ${BIN2C} ${_source} ">${_target}" )
308 endif ()
309endfunction()
diff --git a/llthreads2/dist.info b/llthreads2/dist.info
new file mode 100644
index 0000000..5dfdbaa
--- /dev/null
+++ b/llthreads2/dist.info
@@ -0,0 +1,12 @@
1name = "lua-llthreads2"
2version = "0.1.1"
3
4desc = "A simple Lua wrapper for pthreads & WIN32 threads."
5author = "Alexey Melnichuk"
6license = "MIT/X11"
7url = "https://github.com/moteus/lua-llthreads2"
8maintainer = "Alexey Melnichuk"
9
10depends = {
11 "lua > 5.1"
12} \ No newline at end of file
diff --git a/llthreads2/lakeconfig.lua b/llthreads2/lakeconfig.lua
new file mode 100644
index 0000000..ffe5ad7
--- /dev/null
+++ b/llthreads2/lakeconfig.lua
@@ -0,0 +1,252 @@
1local io = require "io"
2io.stdout:setvbuf"no"
3io.stderr:setvbuf"no"
4
5function vc_version()
6 local VER = lake.compiler_version()
7 MSVC_VER = ({
8 [15] = '9';
9 [16] = '10';
10 })[VER.MAJOR] or ''
11 return MSVC_VER
12end
13
14if not L then
15
16local function arkey(t)
17 assert(type(t) == 'table')
18 local keys = {}
19 for k in pairs(t) do
20 assert(type(k) == 'number')
21 table.insert(keys, k)
22 end
23 table.sort(keys)
24 return keys
25end
26
27local function ikeys(t)
28 local keys = arkey(t)
29 local i = 0
30 return function()
31 i = i + 1
32 local k = keys[i]
33 if k == nil then return end
34 return k, t[k]
35 end
36end
37
38local function expand(arr, t)
39 if t == nil then return arr end
40
41 if type(t) ~= 'table' then
42 table.insert(arr, t)
43 return arr
44 end
45
46 for _, v in ikeys(t) do
47 expand(arr, v)
48 end
49
50 return arr
51end
52
53function L(...)
54 return expand({}, {...})
55end
56
57end
58
59J = J or path.join
60
61IF = IF or lake.choose or choose
62
63DIR_SEP = package.config:sub(1,1)
64
65function prequire(...)
66 local ok, mod = pcall(require, ...)
67 if ok then return mod end
68end
69
70function clone(t, o)
71 o = o or {}
72 for k, v in pairs(t) do
73 if o[k] == nil then o[k] = v end
74 end
75 return o
76end
77
78function each_join(dir, list)
79 for i, v in ipairs(list) do
80 list[i] = path.join(dir, v)
81 end
82 return list
83end
84
85function run(file, cwd)
86 print()
87 print("run " .. file)
88 if not TESTING then
89 if cwd then lake.chdir(cwd) end
90 local status, code = utils.execute( LUA_RUNNER .. ' ' .. file )
91 if cwd then lake.chdir("<") end
92 print()
93 return status, code
94 end
95 return true, 0
96end
97
98function exec(file, cwd)
99 print()
100 print("exec " .. file)
101 if not TESTING then
102 if cwd then lake.chdir(cwd) end
103 local status, code = utils.execute( file )
104 if cwd then lake.chdir("<") end
105 print()
106 return status, code
107 end
108 return true, 0
109end
110
111local TESTS = {}
112
113function run_test(name, params)
114 local test_dir = TESTDIR or J(ROOT, 'test')
115 local cmd = J(test_dir, name)
116 if params then cmd = cmd .. ' ' .. params end
117 local ok = run(cmd, test_dir)
118
119 table.insert(TESTS, {cmd = cmd, result = ok})
120
121 print("TEST " .. name .. (ok and ' - pass!' or ' - fail!'))
122end
123
124function exec_test(name, params)
125 local test_dir = TESTDIR or J(ROOT, 'test')
126 local cmd = J(test_dir, name)
127 if params then cmd = cmd .. ' ' .. params end
128 local ok = exec(cmd, test_dir)
129
130 table.insert(TESTS, {cmd = cmd, result = ok})
131
132 print("TEST " .. name .. (ok and ' - pass!' or ' - fail!'))
133end
134
135function test_summary()
136 local ok = true
137 print("")
138 print("------------------------------------")
139 print("Number of tests:", #TESTS)
140 for _, t in ipairs(TESTS) do
141 ok = ok and t.result
142 print((t.result and ' Pass' or ' Fail') .. " - TEST " .. t.cmd)
143 end
144 print("------------------------------------")
145 print("")
146 return ok
147end
148
149--[[spawn]] if WINDOWS then
150 function spawn(file, cwd)
151 local winapi = prequire "winapi"
152 if not winapi then
153 quit('needs winapi for spawn!')
154 return false
155 end
156
157 print("spawn " .. file)
158 if not TESTING then
159 if cwd then lake.chdir(cwd) end
160 assert(winapi.shell_exec(nil, LUA_RUNNER, file, cwd))
161 if cwd then lake.chdir("<") end
162 print()
163 end
164 return true
165 end
166else
167 function spawn(file, cwd)
168 print("spawn " .. file)
169 if not TESTING then
170 assert(run(file .. ' &', cwd))
171 end
172 return true
173 end
174end
175
176function as_bool(v,d)
177 if v == nil then return not not d end
178 local n = tonumber(v)
179 if n == 0 then return false end
180 if n then return true end
181 return false
182end
183
184--- set global variables
185-- LUA_NEED
186-- LUA_DIR
187-- LUA_RUNNER
188-- ROOT
189-- LUADIR
190-- LIBDIR
191-- TESTDIR
192-- DOCDIR
193-- DYNAMIC
194function INITLAKEFILE()
195 if LUA_VER == '5.3' then
196 LUA_NEED = 'lua53'
197 LUA_DIR = ENV.LUA_DIR_5_3 or ENV.LUA_DIR
198 LUA_RUNNER = LUA_RUNNER or 'lua53'
199 elseif LUA_VER == '5.2' then
200 LUA_NEED = 'lua52'
201 LUA_DIR = ENV.LUA_DIR_5_2 or ENV.LUA_DIR
202 LUA_RUNNER = LUA_RUNNER or 'lua52'
203 elseif LUA_VER == '5.1' then
204 LUA_NEED = 'lua51'
205 LUA_DIR = ENV.LUA_DIR
206 LUA_RUNNER = LUA_RUNNER or 'lua'
207 else
208 LUA_NEED = 'lua'
209 LUA_DIR = ENV.LUA_DIR
210 LUA_RUNNER = LUA_RUNNER or 'lua'
211 end
212 ROOT = ROOT or J( LUA_DIR, 'libs', PROJECT )
213 LUADIR = LUADIR or J( ROOT, 'share' )
214 LIBDIR = LIBDIR or J( ROOT, 'share' )
215 TESTDIR = TESTDIR or J( ROOT, 'test' )
216 DOCDIR = DOCDIR or J( ROOT, 'doc' )
217 DYNAMIC = as_bool(DYNAMIC, false)
218end
219
220-----------------------
221-- needs --
222-----------------------
223
224lake.define_need('lua53', function()
225 return {
226 incdir = J(ENV.LUA_DIR_5_3, 'include');
227 libdir = J(ENV.LUA_DIR_5_3, 'lib');
228 libs = {'lua53'};
229 }
230end)
231
232lake.define_need('lua52', function()
233 return {
234 incdir = J(ENV.LUA_DIR_5_2, 'include');
235 libdir = J(ENV.LUA_DIR_5_2, 'lib');
236 libs = {'lua52'};
237 }
238end)
239
240lake.define_need('lua51', function()
241 return {
242 incdir = J(ENV.LUA_DIR, 'include');
243 libdir = J(ENV.LUA_DIR, 'lib');
244 libs = {'lua5.1'};
245 }
246end)
247
248lake.define_need('pthread', function()
249 return {
250 libs = 'pthread';
251 }
252end) \ No newline at end of file
diff --git a/llthreads2/lakefile b/llthreads2/lakefile
new file mode 100644
index 0000000..64bd3fa
--- /dev/null
+++ b/llthreads2/lakefile
@@ -0,0 +1,45 @@
1PROJECT = 'llthreads'
2
3INITLAKEFILE()
4
5DEFINES = L{DEFINES,
6 IF(WINDOWS, 'DLL_EXPORT', '');
7 IF(not MSVC, 'USE_PTHREAD', '');
8}
9
10core = c.shared{PROJECT,
11 base = 'src',
12 src = '*.c',
13 needs = LUA_NEED,
14 defines = DEFINES,
15 dynamic = DYNAMIC,
16 strip = true,
17 libs = IF(not MSVC, 'pthread');
18}
19
20target('build', core)
21
22install = target('install', {
23 file.group{odir=LIBDIR; src = core };
24 file.group{odir=TESTDIR; src = J('test', '*'); recurse = true };
25})
26
27target('test', install, function()
28 -- run_test('test_register_llthreads.lua')
29 run_test('test_join_timeout.lua')
30 run_test('test_llthreads.lua')
31 run_test('test_table_copy.lua')
32 run_test('test_threads.lua')
33 run_test('test_join_timeout.lua')
34 run_test('test_join_detach.lua')
35 run_test('test_join_error.lua')
36 run_test('test_register_ffi.lua')
37 run_test('test_logger.lua')
38 run_test('test_pass_cfunction.lua')
39 run_test('test_alive.lua')
40
41 if not test_summary() then
42 quit("test fail")
43 end
44end)
45
diff --git a/llthreads2/msvc/llthreads.sln b/llthreads2/msvc/llthreads.sln
new file mode 100644
index 0000000..1277174
--- /dev/null
+++ b/llthreads2/msvc/llthreads.sln
@@ -0,0 +1,20 @@
1
2Microsoft Visual Studio Solution File, Format Version 10.00
3# Visual Studio 2008
4Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "llthreads", "llthreads.vcproj", "{60F3B657-C1F7-47F7-B159-3EEEA6B1220D}"
5EndProject
6Global
7 GlobalSection(SolutionConfigurationPlatforms) = preSolution
8 Debug|Win32 = Debug|Win32
9 Release|Win32 = Release|Win32
10 EndGlobalSection
11 GlobalSection(ProjectConfigurationPlatforms) = postSolution
12 {60F3B657-C1F7-47F7-B159-3EEEA6B1220D}.Debug|Win32.ActiveCfg = Debug|Win32
13 {60F3B657-C1F7-47F7-B159-3EEEA6B1220D}.Debug|Win32.Build.0 = Debug|Win32
14 {60F3B657-C1F7-47F7-B159-3EEEA6B1220D}.Release|Win32.ActiveCfg = Release|Win32
15 {60F3B657-C1F7-47F7-B159-3EEEA6B1220D}.Release|Win32.Build.0 = Release|Win32
16 EndGlobalSection
17 GlobalSection(SolutionProperties) = preSolution
18 HideSolutionNode = FALSE
19 EndGlobalSection
20EndGlobal
diff --git a/llthreads2/msvc/llthreads.vcproj b/llthreads2/msvc/llthreads.vcproj
new file mode 100644
index 0000000..6f6c5bd
--- /dev/null
+++ b/llthreads2/msvc/llthreads.vcproj
@@ -0,0 +1,208 @@
1<?xml version="1.0" encoding="windows-1251"?>
2<VisualStudioProject
3 ProjectType="Visual C++"
4 Version="9,00"
5 Name="llthreads"
6 ProjectGUID="{60F3B657-C1F7-47F7-B159-3EEEA6B1220D}"
7 RootNamespace="llthreads"
8 Keyword="Win32Proj"
9 TargetFrameworkVersion="196613"
10 >
11 <Platforms>
12 <Platform
13 Name="Win32"
14 />
15 </Platforms>
16 <ToolFiles>
17 </ToolFiles>
18 <Configurations>
19 <Configuration
20 Name="Debug|Win32"
21 OutputDirectory="$(SolutionDir)$(ConfigurationName)"
22 IntermediateDirectory="$(ConfigurationName)"
23 ConfigurationType="2"
24 CharacterSet="1"
25 >
26 <Tool
27 Name="VCPreBuildEventTool"
28 />
29 <Tool
30 Name="VCCustomBuildTool"
31 />
32 <Tool
33 Name="VCXMLDataGeneratorTool"
34 />
35 <Tool
36 Name="VCWebServiceProxyGeneratorTool"
37 />
38 <Tool
39 Name="VCMIDLTool"
40 />
41 <Tool
42 Name="VCCLCompilerTool"
43 Optimization="0"
44 AdditionalIncludeDirectories="$(LUA_DIR_5_2)\include"
45 PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;LLTHREADS_EXPORTS"
46 MinimalRebuild="true"
47 BasicRuntimeChecks="3"
48 RuntimeLibrary="3"
49 UsePrecompiledHeader="0"
50 WarningLevel="3"
51 DebugInformationFormat="4"
52 />
53 <Tool
54 Name="VCManagedResourceCompilerTool"
55 />
56 <Tool
57 Name="VCResourceCompilerTool"
58 />
59 <Tool
60 Name="VCPreLinkEventTool"
61 />
62 <Tool
63 Name="VCLinkerTool"
64 AdditionalOptions="/EXPORT:luaopen_llthreads"
65 AdditionalDependencies="lua52.lib"
66 LinkIncremental="2"
67 AdditionalLibraryDirectories="$(LUA_DIR_5_2)\lib"
68 GenerateDebugInformation="true"
69 SubSystem="2"
70 TargetMachine="1"
71 />
72 <Tool
73 Name="VCALinkTool"
74 />
75 <Tool
76 Name="VCManifestTool"
77 />
78 <Tool
79 Name="VCXDCMakeTool"
80 />
81 <Tool
82 Name="VCBscMakeTool"
83 />
84 <Tool
85 Name="VCFxCopTool"
86 />
87 <Tool
88 Name="VCAppVerifierTool"
89 />
90 <Tool
91 Name="VCPostBuildEventTool"
92 />
93 </Configuration>
94 <Configuration
95 Name="Release|Win32"
96 OutputDirectory="$(SolutionDir)$(ConfigurationName)"
97 IntermediateDirectory="$(ConfigurationName)"
98 ConfigurationType="2"
99 CharacterSet="1"
100 WholeProgramOptimization="1"
101 >
102 <Tool
103 Name="VCPreBuildEventTool"
104 />
105 <Tool
106 Name="VCCustomBuildTool"
107 />
108 <Tool
109 Name="VCXMLDataGeneratorTool"
110 />
111 <Tool
112 Name="VCWebServiceProxyGeneratorTool"
113 />
114 <Tool
115 Name="VCMIDLTool"
116 />
117 <Tool
118 Name="VCCLCompilerTool"
119 Optimization="2"
120 EnableIntrinsicFunctions="true"
121 AdditionalIncludeDirectories="$(LUA_DIR_5_2)\include"
122 PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;LLTHREADS_EXPORTS"
123 RuntimeLibrary="2"
124 EnableFunctionLevelLinking="true"
125 UsePrecompiledHeader="0"
126 WarningLevel="3"
127 DebugInformationFormat="3"
128 />
129 <Tool
130 Name="VCManagedResourceCompilerTool"
131 />
132 <Tool
133 Name="VCResourceCompilerTool"
134 />
135 <Tool
136 Name="VCPreLinkEventTool"
137 />
138 <Tool
139 Name="VCLinkerTool"
140 AdditionalDependencies="lua52.lib"
141 LinkIncremental="1"
142 AdditionalLibraryDirectories="$(LUA_DIR_5_2)\lib"
143 GenerateDebugInformation="true"
144 SubSystem="2"
145 OptimizeReferences="2"
146 EnableCOMDATFolding="2"
147 TargetMachine="1"
148 />
149 <Tool
150 Name="VCALinkTool"
151 />
152 <Tool
153 Name="VCManifestTool"
154 />
155 <Tool
156 Name="VCXDCMakeTool"
157 />
158 <Tool
159 Name="VCBscMakeTool"
160 />
161 <Tool
162 Name="VCFxCopTool"
163 />
164 <Tool
165 Name="VCAppVerifierTool"
166 />
167 <Tool
168 Name="VCPostBuildEventTool"
169 />
170 </Configuration>
171 </Configurations>
172 <References>
173 </References>
174 <Files>
175 <Filter
176 Name="Source Files"
177 Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
178 UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
179 >
180 </Filter>
181 <Filter
182 Name="Header Files"
183 Filter="h;hpp;hxx;hm;inl;inc;xsd"
184 UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
185 >
186 <File
187 RelativePath="..\src\l52util.h"
188 >
189 </File>
190 </Filter>
191 <Filter
192 Name="Resource Files"
193 Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
194 UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
195 >
196 <File
197 RelativePath="..\src\l52util.c"
198 >
199 </File>
200 <File
201 RelativePath="..\src\llthread.c"
202 >
203 </File>
204 </Filter>
205 </Files>
206 <Globals>
207 </Globals>
208</VisualStudioProject>
diff --git a/llthreads2/rockspecs/lua-llthreads2-0.1.0-1.rockspec b/llthreads2/rockspecs/lua-llthreads2-0.1.0-1.rockspec
new file mode 100644
index 0000000..9116d6a
--- /dev/null
+++ b/llthreads2/rockspecs/lua-llthreads2-0.1.0-1.rockspec
@@ -0,0 +1,44 @@
1package = "lua-llthreads2"
2version = "0.1.0-1"
3source = {
4 url = "https://github.com/moteus/lua-llthreads2/archive/v0.1.0.zip",
5 dir = "lua-llthreads2-0.1.0",
6}
7description = {
8 summary = "Low-Level threads for Lua",
9 homepage = "http://github.com/moteus/lua-llthreads2",
10 license = "MIT/X11",
11 detailed = [[
12 This is drop-in replacement for `lua-llthread` module but the module called `llthreads2`.
13 In additional module supports: thread join with zero timeout; logging thread errors with
14 custom logger; run detached joinable threads; pass cfunctions as argument to child thread.
15 ]],
16}
17dependencies = {
18 "lua >= 5.1, < 5.3",
19}
20build = {
21 type = "builtin",
22 platforms = {
23 unix = {
24 modules = {
25 llthreads2 = {
26 libraries = {"pthread"},
27 }
28 }
29 },
30 windows = {
31 modules = {
32 llthreads2 = {
33 libraries = {"kernel32"},
34 }
35 }
36 }
37 },
38 modules = {
39 llthreads2 = {
40 sources = { "src/l52util.c", "src/llthread.c" },
41 defines = { "LLTHREAD_MODULE_NAME=llthreads2" },
42 }
43 }
44} \ No newline at end of file
diff --git a/llthreads2/rockspecs/lua-llthreads2-0.1.1-1.rockspec b/llthreads2/rockspecs/lua-llthreads2-0.1.1-1.rockspec
new file mode 100644
index 0000000..af74686
--- /dev/null
+++ b/llthreads2/rockspecs/lua-llthreads2-0.1.1-1.rockspec
@@ -0,0 +1,44 @@
1package = "lua-llthreads2"
2version = "0.1.1-1"
3source = {
4 url = "https://github.com/moteus/lua-llthreads2/archive/v0.1.1.zip",
5 dir = "lua-llthreads2-0.1.1",
6}
7description = {
8 summary = "Low-Level threads for Lua",
9 homepage = "http://github.com/moteus/lua-llthreads2",
10 license = "MIT/X11",
11 detailed = [[
12 This is drop-in replacement for `lua-llthread` module but the module called `llthreads2`.
13 In additional module supports: thread join with zero timeout; logging thread errors with
14 custom logger; run detached joinable threads; pass cfunctions as argument to child thread.
15 ]],
16}
17dependencies = {
18 "lua >= 5.1, < 5.3",
19}
20build = {
21 type = "builtin",
22 platforms = {
23 unix = {
24 modules = {
25 llthreads2 = {
26 libraries = {"pthread"},
27 }
28 }
29 },
30 windows = {
31 modules = {
32 llthreads2 = {
33 libraries = {"kernel32"},
34 }
35 }
36 }
37 },
38 modules = {
39 llthreads2 = {
40 sources = { "src/l52util.c", "src/llthread.c" },
41 defines = { "LLTHREAD_MODULE_NAME=llthreads2" },
42 }
43 }
44} \ No newline at end of file
diff --git a/llthreads2/rockspecs/lua-llthreads2-compat-0.1.0-1.rockspec b/llthreads2/rockspecs/lua-llthreads2-compat-0.1.0-1.rockspec
new file mode 100644
index 0000000..0c058ea
--- /dev/null
+++ b/llthreads2/rockspecs/lua-llthreads2-compat-0.1.0-1.rockspec
@@ -0,0 +1,44 @@
1package = "lua-llthreads2-compat"
2version = "0.1.0-1"
3source = {
4 url = "https://github.com/moteus/lua-llthreads2/archive/v0.1.0.zip",
5 dir = "lua-llthreads2-0.1.0",
6}
7description = {
8 summary = "Low-Level threads for Lua",
9 homepage = "http://github.com/moteus/lua-llthreads2",
10 license = "MIT/X11",
11 detailed = [[
12 This is drop-in replacement for `lua-llthread` module.
13 In additional module supports: thread join with zero timeout; logging thread errors with
14 custom logger; run detached joinable threads; pass cfunctions as argument to child thread.
15 ]],
16}
17dependencies = {
18 "lua >= 5.1, < 5.3",
19}
20build = {
21 type = "builtin",
22 platforms = {
23 unix = {
24 modules = {
25 llthreads = {
26 libraries = {"pthread"},
27 }
28 }
29 },
30 windows = {
31 modules = {
32 llthreads = {
33 libraries = {"kernel32"},
34 }
35 }
36 }
37 },
38 modules = {
39 llthreads = {
40 sources = { "src/l52util.c", "src/llthread.c" },
41 defines = { "LLTHREAD_MODULE_NAME=llthreads" },
42 }
43 }
44} \ No newline at end of file
diff --git a/llthreads2/rockspecs/lua-llthreads2-compat-0.1.1-1.rockspec b/llthreads2/rockspecs/lua-llthreads2-compat-0.1.1-1.rockspec
new file mode 100644
index 0000000..75ef40e
--- /dev/null
+++ b/llthreads2/rockspecs/lua-llthreads2-compat-0.1.1-1.rockspec
@@ -0,0 +1,44 @@
1package = "lua-llthreads2-compat"
2version = "0.1.1-1"
3source = {
4 url = "https://github.com/moteus/lua-llthreads2/archive/v0.1.1.zip",
5 dir = "lua-llthreads2-0.1.1",
6}
7description = {
8 summary = "Low-Level threads for Lua",
9 homepage = "http://github.com/moteus/lua-llthreads2",
10 license = "MIT/X11",
11 detailed = [[
12 This is drop-in replacement for `lua-llthread` module.
13 In additional module supports: thread join with zero timeout; logging thread errors with
14 custom logger; run detached joinable threads; pass cfunctions as argument to child thread.
15 ]],
16}
17dependencies = {
18 "lua >= 5.1, < 5.3",
19}
20build = {
21 type = "builtin",
22 platforms = {
23 unix = {
24 modules = {
25 llthreads = {
26 libraries = {"pthread"},
27 }
28 }
29 },
30 windows = {
31 modules = {
32 llthreads = {
33 libraries = {"kernel32"},
34 }
35 }
36 }
37 },
38 modules = {
39 llthreads = {
40 sources = { "src/l52util.c", "src/llthread.c" },
41 defines = { "LLTHREAD_MODULE_NAME=llthreads" },
42 }
43 }
44} \ No newline at end of file
diff --git a/llthreads2/rockspecs/lua-llthreads2-compat-scm-0.rockspec b/llthreads2/rockspecs/lua-llthreads2-compat-scm-0.rockspec
new file mode 100644
index 0000000..ac81a15
--- /dev/null
+++ b/llthreads2/rockspecs/lua-llthreads2-compat-scm-0.rockspec
@@ -0,0 +1,44 @@
1package = "lua-llthreads2-compat"
2version = "scm-0"
3source = {
4 url = "https://github.com/moteus/lua-llthreads2/archive/master.zip",
5 dir = "lua-llthreads2-master",
6}
7description = {
8 summary = "Low-Level threads for Lua",
9 homepage = "http://github.com/moteus/lua-llthreads2",
10 license = "MIT/X11",
11 detailed = [[
12 This is drop-in replacement for `lua-llthread` module.
13 In additional module supports: thread join with zero timeout; logging thread errors with
14 custom logger; run detached joinable threads; pass cfunctions as argument to child thread.
15 ]],
16}
17dependencies = {
18 "lua >= 5.1, < 5.3",
19}
20build = {
21 type = "builtin",
22 platforms = {
23 unix = {
24 modules = {
25 llthreads = {
26 libraries = {"pthread"},
27 }
28 }
29 },
30 windows = {
31 modules = {
32 llthreads = {
33 libraries = {"kernel32"},
34 }
35 }
36 }
37 },
38 modules = {
39 llthreads = {
40 sources = { "src/l52util.c", "src/llthread.c" },
41 defines = { "LLTHREAD_MODULE_NAME=llthreads" },
42 }
43 }
44} \ No newline at end of file
diff --git a/llthreads2/rockspecs/lua-llthreads2-scm-0.rockspec b/llthreads2/rockspecs/lua-llthreads2-scm-0.rockspec
new file mode 100644
index 0000000..87f9b15
--- /dev/null
+++ b/llthreads2/rockspecs/lua-llthreads2-scm-0.rockspec
@@ -0,0 +1,44 @@
1package = "lua-llthreads2"
2version = "scm-0"
3source = {
4 url = "https://github.com/moteus/lua-llthreads2/archive/master.zip",
5 dir = "lua-llthreads2-master",
6}
7description = {
8 summary = "Low-Level threads for Lua",
9 homepage = "http://github.com/moteus/lua-llthreads2",
10 license = "MIT/X11",
11 detailed = [[
12 This is drop-in replacement for `lua-llthread` module but the module called `llthreads2`.
13 In additional module supports: thread join with zero timeout; logging thread errors with
14 custom logger; run detached joinable threads; pass cfunctions as argument to child thread.
15 ]],
16}
17dependencies = {
18 "lua >= 5.1, < 5.3",
19}
20build = {
21 type = "builtin",
22 platforms = {
23 unix = {
24 modules = {
25 llthreads2 = {
26 libraries = {"pthread"},
27 }
28 }
29 },
30 windows = {
31 modules = {
32 llthreads2 = {
33 libraries = {"kernel32"},
34 }
35 }
36 }
37 },
38 modules = {
39 llthreads2 = {
40 sources = { "src/l52util.c", "src/llthread.c" },
41 defines = { "LLTHREAD_MODULE_NAME=llthreads2" },
42 }
43 }
44} \ No newline at end of file
diff --git a/llthreads2/src/copy.inc b/llthreads2/src/copy.inc
new file mode 100644
index 0000000..21ba261
--- /dev/null
+++ b/llthreads2/src/copy.inc
@@ -0,0 +1,170 @@
1/******************************************************************************
2* Copyright (c) 2011 by Robert G. Jakabosky <bobby@sharedrealm.com>
3*
4* Permission is hereby granted, free of charge, to any person obtaining a copy
5* of this software and associated documentation files (the "Software"), to deal
6* in the Software without restriction, including without limitation the rights
7* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8* copies of the Software, and to permit persons to whom the Software is
9* furnished to do so, subject to the following conditions:
10*
11* The above copyright notice and this permission notice shall be included in
12* all copies or substantial portions of the Software.
13*
14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20* THE SOFTWARE.
21******************************************************************************/
22
23/* maximum recursive depth of table copies. */
24#define MAX_COPY_DEPTH 30
25
26typedef struct {
27 lua_State *from_L;
28 lua_State *to_L;
29 int has_cache;
30 int cache_idx;
31 int is_arg;
32} llthread_copy_state;
33
34static int llthread_copy_table_from_cache(llthread_copy_state *state, int idx) {
35 void *ptr;
36
37 /* convert table to pointer for lookup in cache. */
38 ptr = (void *)lua_topointer(state->from_L, idx);
39 if(ptr == NULL) return 0; /* can't convert to pointer. */
40
41 /* check if we need to create the cache. */
42 if(!state->has_cache) {
43 lua_newtable(state->to_L);
44 lua_replace(state->to_L, state->cache_idx);
45 state->has_cache = 1;
46 }
47
48 lua_pushlightuserdata(state->to_L, ptr);
49 lua_rawget(state->to_L, state->cache_idx);
50 if(lua_isnil(state->to_L, -1)) {
51 /* not in cache. */
52 lua_pop(state->to_L, 1);
53 /* create new table and add to cache. */
54 lua_newtable(state->to_L);
55 lua_pushlightuserdata(state->to_L, ptr);
56 lua_pushvalue(state->to_L, -2);
57 lua_rawset(state->to_L, state->cache_idx);
58 return 0;
59 }
60 /* found table in cache. */
61 return 1;
62}
63
64static int llthread_copy_value(llthread_copy_state *state, int depth, int idx) {
65 const char *str;
66 size_t str_len;
67 int kv_pos;
68
69 /* Maximum recursive depth */
70 if(++depth > MAX_COPY_DEPTH) {
71 return luaL_error(state->from_L, "Hit maximum copy depth (%d > %d).", depth, MAX_COPY_DEPTH);
72 }
73
74 /* only support string/number/boolean/nil/table/lightuserdata. */
75 switch(lua_type(state->from_L, idx)) {
76 case LUA_TNIL:
77 lua_pushnil(state->to_L);
78 break;
79 case LUA_TNUMBER:
80 lua_pushnumber(state->to_L, lua_tonumber(state->from_L, idx));
81 break;
82 case LUA_TBOOLEAN:
83 lua_pushboolean(state->to_L, lua_toboolean(state->from_L, idx));
84 break;
85 case LUA_TSTRING:
86 str = lua_tolstring(state->from_L, idx, &(str_len));
87 lua_pushlstring(state->to_L, str, str_len);
88 break;
89 case LUA_TLIGHTUSERDATA:
90 lua_pushlightuserdata(state->to_L, lua_touserdata(state->from_L, idx));
91 break;
92 case LUA_TTABLE:
93 /* make sure there is room on the new state for 3 values (table,key,value) */
94 if(!lua_checkstack(state->to_L, 3)) {
95 return luaL_error(state->from_L, "To stack overflow!");
96 }
97 /* make room on from stack for key/value pairs. */
98 luaL_checkstack(state->from_L, 2, "From stack overflow!");
99
100 /* check cache for table. */
101 if(llthread_copy_table_from_cache(state, idx)) {
102 /* found in cache don't need to copy table. */
103 break;
104 }
105 lua_pushnil(state->from_L);
106 while (lua_next(state->from_L, idx) != 0) {
107 /* key is at (top - 1), value at (top), but we need to normalize these
108 * to positive indices */
109 kv_pos = lua_gettop(state->from_L);
110 /* copy key */
111 llthread_copy_value(state, depth, kv_pos - 1);
112 /* copy value */
113 llthread_copy_value(state, depth, kv_pos);
114 /* Copied key and value are now at -2 and -1 in state->to_L. */
115 lua_settable(state->to_L, -3);
116 /* Pop value for next iteration */
117 lua_pop(state->from_L, 1);
118 }
119 break;
120 case LUA_TFUNCTION:
121 if(lua_iscfunction(state->from_L, idx)){
122 lua_CFunction fn = lua_tocfunction(state->from_L, idx);
123 lua_pushcfunction(state->to_L, fn);
124 break;
125 }
126 case LUA_TUSERDATA:
127 case LUA_TTHREAD:
128 default:
129 if (state->is_arg) {
130 return luaL_argerror(state->from_L, idx, "function/userdata/thread types un-supported.");
131 } else {
132 /* convert un-supported types to an error string. */
133 lua_pushfstring(state->to_L, "Un-supported value: %s: %p",
134 lua_typename(state->from_L, lua_type(state->from_L, idx)), lua_topointer(state->from_L, idx));
135 }
136 }
137
138 return 1;
139}
140
141static int llthread_copy_values(lua_State *from_L, lua_State *to_L, int idx, int top, int is_arg) {
142 llthread_copy_state state;
143 int nvalues = 0;
144 int n;
145
146 nvalues = (top - idx) + 1;
147 /* make sure there is room on the new state for the values. */
148 if(!lua_checkstack(to_L, nvalues + 1)) {
149 return luaL_error(from_L, "To stack overflow!");
150 }
151
152 /* setup copy state. */
153 state.from_L = from_L;
154 state.to_L = to_L;
155 state.is_arg = is_arg;
156 state.has_cache = 0; /* don't create cache table unless it is needed. */
157 lua_pushnil(to_L);
158 state.cache_idx = lua_gettop(to_L);
159
160 nvalues = 0;
161 for(n = idx; n <= top; n++) {
162 llthread_copy_value(&state, 0, n);
163 ++nvalues;
164 }
165
166 /* remove cache table. */
167 lua_remove(to_L, state.cache_idx);
168
169 return nvalues;
170}
diff --git a/llthreads2/src/l52util.c b/llthreads2/src/l52util.c
new file mode 100644
index 0000000..9d44a40
--- /dev/null
+++ b/llthreads2/src/l52util.c
@@ -0,0 +1,126 @@
1#include "l52util.h"
2
3#include <memory.h>
4#include <assert.h>
5
6#if LUA_VERSION_NUM >= 502
7
8int luaL_typerror (lua_State *L, int narg, const char *tname) {
9 const char *msg = lua_pushfstring(L, "%s expected, got %s", tname,
10 luaL_typename(L, narg));
11 return luaL_argerror(L, narg, msg);
12}
13
14#ifndef luaL_register
15
16void luaL_register (lua_State *L, const char *libname, const luaL_Reg *l){
17 if(libname) lua_newtable(L);
18 luaL_setfuncs(L, l, 0);
19}
20
21#endif
22
23#else
24
25void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup){
26 luaL_checkstack(L, nup, "too many upvalues");
27 for (; l->name != NULL; l++) { /* fill the table with given functions */
28 int i;
29 for (i = 0; i < nup; i++) /* copy upvalues to the top */
30 lua_pushvalue(L, -nup);
31 lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */
32 lua_setfield(L, -(nup + 2), l->name);
33 }
34 lua_pop(L, nup); /* remove upvalues */
35}
36
37void lua_rawgetp(lua_State *L, int index, const void *p){
38 index = lua_absindex(L, index);
39 lua_pushlightuserdata(L, (void *)p);
40 lua_rawget(L, index);
41}
42
43void lua_rawsetp (lua_State *L, int index, const void *p){
44 index = lua_absindex(L, index);
45 lua_pushlightuserdata(L, (void *)p);
46 lua_insert(L, -2);
47 lua_rawset(L, index);
48}
49
50void lutil_require(lua_State *L, const char* name, lua_CFunction fn, int glb) {
51 // @fixme generate error if we can not load module
52 lua_cpcall(L, fn, NULL);
53}
54
55#endif
56
57int lutil_newmetatablep (lua_State *L, const void *p) {
58 lua_rawgetp(L, LUA_REGISTRYINDEX, p);
59 if (!lua_isnil(L, -1)) /* name already in use? */
60 return 0; /* leave previous value on top, but return 0 */
61 lua_pop(L, 1);
62
63 lua_newtable(L); /* create metatable */
64 lua_pushvalue(L, -1); /* duplicate metatable to set*/
65 lua_rawsetp(L, LUA_REGISTRYINDEX, p);
66
67 return 1;
68}
69
70void lutil_getmetatablep (lua_State *L, const void *p) {
71 lua_rawgetp(L, LUA_REGISTRYINDEX, p);
72}
73
74void lutil_setmetatablep (lua_State *L, const void *p) {
75 lutil_getmetatablep(L, p);
76 assert(lua_istable(L,-1));
77 lua_setmetatable (L, -2);
78}
79
80int lutil_isudatap (lua_State *L, int ud, const void *p) {
81 if (lua_isuserdata(L, ud)){
82 if (lua_getmetatable(L, ud)) { /* does it have a metatable? */
83 int res;
84 lutil_getmetatablep(L,p); /* get correct metatable */
85 res = lua_rawequal(L, -1, -2); /* does it have the correct mt? */
86 lua_pop(L, 2); /* remove both metatables */
87 return res;
88 }
89 }
90 return 0;
91}
92
93void *lutil_checkudatap (lua_State *L, int ud, const void *p) {
94 void *up = lua_touserdata(L, ud);
95 if (up != NULL) { /* value is a userdata? */
96 if (lua_getmetatable(L, ud)) { /* does it have a metatable? */
97 lutil_getmetatablep(L,p); /* get correct metatable */
98 if (lua_rawequal(L, -1, -2)) { /* does it have the correct mt? */
99 lua_pop(L, 2); /* remove both metatables */
100 return up;
101 }
102 }
103 }
104 luaL_typerror(L, ud, p); /* else error */
105 return NULL; /* to avoid warnings */
106}
107
108int lutil_createmetap (lua_State *L, const void *p, const luaL_Reg *methods, int nup) {
109 if (!lutil_newmetatablep(L, p))
110 return 0;
111
112 lua_insert(L, -1 - nup); /* move mt prior upvalues */
113 luaL_setfuncs (L, methods, nup); /* define methods */
114 lua_pushliteral (L, "__index"); /* define metamethods */
115 lua_pushvalue (L, -2);
116 lua_settable (L, -3);
117
118 return 1;
119}
120
121void *lutil_newudatap_impl(lua_State *L, size_t size, const void *p){
122 void *obj = lua_newuserdata (L, size);
123 memset(obj, 0, size);
124 lutil_setmetatablep(L, p);
125 return obj;
126}
diff --git a/llthreads2/src/l52util.h b/llthreads2/src/l52util.h
new file mode 100644
index 0000000..38a87db
--- /dev/null
+++ b/llthreads2/src/l52util.h
@@ -0,0 +1,57 @@
1#ifndef _LZUTILS_H_9B43D914_9652_4E22_9A43_8073502BF3F4_
2#define _LZUTILS_H_9B43D914_9652_4E22_9A43_8073502BF3F4_
3
4#include "lua.h"
5#include "lauxlib.h"
6
7#if LUA_VERSION_NUM >= 502 // lua 5.2
8
9// lua_rawgetp
10// lua_rawsetp
11// luaL_setfuncs
12// lua_absindex
13
14#ifndef lua_objlen
15
16#define lua_objlen lua_rawlen
17
18#endif
19
20int luaL_typerror (lua_State *L, int narg, const char *tname);
21
22#ifndef luaL_register
23
24void luaL_register (lua_State *L, const char *libname, const luaL_Reg *l);
25
26#endif
27
28#define lutil_require luaL_requiref
29
30#else // lua 5.1
31
32// functions form lua 5.2
33
34# define lua_absindex(L, i) (((i)>0)?(i):((i)<=LUA_REGISTRYINDEX?(i):(lua_gettop(L)+(i)+1)))
35# define lua_rawlen lua_objlen
36
37void lua_rawgetp (lua_State *L, int index, const void *p);
38void lua_rawsetp (lua_State *L, int index, const void *p);
39void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup);
40
41void lutil_require(lua_State *L, const char* name, lua_CFunction fn, int glb);
42
43#endif
44
45int lutil_newmetatablep (lua_State *L, const void *p);
46void lutil_getmetatablep (lua_State *L, const void *p);
47void lutil_setmetatablep (lua_State *L, const void *p);
48
49#define lutil_newudatap(L, TTYPE, TNAME) (TTYPE *)lutil_newudatap_impl(L, sizeof(TTYPE), TNAME)
50int lutil_isudatap (lua_State *L, int ud, const void *p);
51void *lutil_checkudatap (lua_State *L, int ud, const void *p);
52int lutil_createmetap (lua_State *L, const void *p, const luaL_Reg *methods, int nup);
53
54void *lutil_newudatap_impl (lua_State *L, size_t size, const void *p);
55
56#endif
57
diff --git a/llthreads2/src/llthread.c b/llthreads2/src/llthread.c
new file mode 100644
index 0000000..0ffa727
--- /dev/null
+++ b/llthreads2/src/llthread.c
@@ -0,0 +1,746 @@
1#if !defined(_WIN32) && !defined(USE_PTHREAD)
2# define USE_PTHREAD
3#endif
4
5#define LLTHREAD_VERSION_MAJOR 0
6#define LLTHREAD_VERSION_MINOR 1
7#define LLTHREAD_VERSION_PATCH 0
8#define LLTHREAD_VERSION_COMMENT ""
9
10#ifndef USE_PTHREAD
11# include <windows.h>
12# include <process.h>
13#else
14# include <pthread.h>
15#endif
16
17#include <stdlib.h>
18#include <stdio.h>
19#include <memory.h>
20#include <assert.h>
21#include <errno.h>
22#include <lualib.h>
23#include "l52util.h"
24#include "traceback.inc"
25#include "copy.inc"
26
27/*export*/
28#ifdef _WIN32
29# define LLTHREADS_EXPORT_API __declspec(dllexport)
30#else
31# define LLTHREADS_EXPORT_API LUALIB_API
32#endif
33
34/* wrap strerror_s(). */
35#ifdef _WIN32
36# ifdef __GNUC__
37# ifndef strerror_r
38# define strerror_r(errno, buf, buflen) do { \
39 strncpy((buf), strerror(errno), (buflen)-1); \
40 (buf)[(buflen)-1] = '\0'; \
41 } while(0)
42# endif
43# else
44# ifndef strerror_r
45# define strerror_r(errno, buf, buflen) strerror_s((buf), (buflen), (errno))
46# endif
47# endif
48#endif
49
50#ifndef USE_PTHREAD
51# define OS_THREAD_RETURN unsigned int __stdcall
52# define INVALID_THREAD INVALID_HANDLE_VALUE
53# define INFINITE_JOIN_TIMEOUT INFINITE
54# define JOIN_OK 0
55# define JOIN_ETIMEDOUT 1
56# define JOIN_FAIL 2
57typedef DWORD join_timeout_t;
58typedef HANDLE os_thread_t;
59#else
60# define OS_THREAD_RETURN void *
61# define INFINITE_JOIN_TIMEOUT -1
62# define JOIN_OK 0
63# define JOIN_ETIMEDOUT ETIMEDOUT
64typedef int join_timeout_t;
65typedef pthread_t os_thread_t;
66#endif
67
68#define ERROR_LEN 1024
69
70#define flags_t unsigned char
71
72#define FLAG_NONE (flags_t)0
73#define FLAG_STARTED (flags_t)1<<0
74#define FLAG_DETACHED (flags_t)1<<1
75#define FLAG_JOINED (flags_t)1<<2
76#define FLAG_JOINABLE (flags_t)1<<3
77
78/*At least one flag*/
79#define FLAG_IS_SET(O, F) (O->flags & (flags_t)(F))
80#define FLAG_SET(O, F) O->flags |= (flags_t)(F)
81#define FLAG_UNSET(O, F) O->flags &= ~((flags_t)(F))
82#define IS(O, F) FLAG_IS_SET(O, FLAG_##F)
83#define SET(O, F) FLAG_SET(O, FLAG_##F)
84
85#define ALLOC_STRUCT(S) (S*)calloc(1, sizeof(S))
86#define FREE_STRUCT(O) free(O)
87
88#ifndef LLTHREAD_MODULE_NAME
89# define LLTHREAD_MODULE_NAME llthreads
90#endif
91
92#define CAT(S1,S2) S1##S2
93
94#define LLTHREAD_OPEN_NAME_IMPL(NAME) CAT(luaopen_, NAME)
95
96#define LLTHREAD_OPEN_NAME LLTHREAD_OPEN_NAME_IMPL(LLTHREAD_MODULE_NAME)
97
98LLTHREADS_EXPORT_API int LLTHREAD_OPEN_NAME(lua_State *L);
99
100#define LLTHREAD_NAME "LLThread"
101static const char *LLTHREAD_TAG = LLTHREAD_NAME;
102static const char *LLTHREAD_LOGGER_HOLDER = LLTHREAD_NAME " logger holder";
103
104typedef struct llthread_child_t {
105 lua_State *L;
106 int status;
107 flags_t flags;
108} llthread_child_t;
109
110typedef struct llthread_t {
111 llthread_child_t *child;
112 os_thread_t thread;
113 flags_t flags;
114} llthread_t;
115
116static int fail(lua_State *L, const char *msg){
117 lua_pushnil(L);
118 lua_pushstring(L, msg);
119 return 2;
120}
121
122//{ logger interface
123void llthread_log(lua_State *L, const char *hdr, const char *msg){
124 int top = lua_gettop(L);
125 lua_rawgetp(L, LUA_REGISTRYINDEX, LLTHREAD_LOGGER_HOLDER);
126 if(lua_isnil(L, -1)){
127 lua_pop(L, 1);
128 fputs(hdr, stderr);
129 fputs(msg, stderr);
130 fputc('\n', stderr);
131 fflush(stderr);
132 return;
133 }
134 lua_pushstring(L, hdr);
135 lua_pushstring(L, msg);
136 lua_concat(L, 2);
137 lua_pcall(L, 1, 0, 0);
138 lua_settop(L, top);
139}
140//}
141
142//{ llthread_child
143
144static void open_thread_libs(lua_State *L){
145#define L_REGLIB(L, name) lua_pushcfunction(L, luaopen_##name); lua_setfield(L, -2)
146
147 int top = lua_gettop(L);
148
149#ifndef LLTHREAD_REGISTER_STD_LIBRARY
150
151 luaL_openlibs(L);
152 lua_getglobal(L, "package"); lua_getfield(L, -1, "preload"); lua_remove(L, -2);
153
154#else
155
156 lutil_require(L, "_G", luaopen_base, 1);
157 lutil_require(L, "package", luaopen_package, 1);
158 lua_settop(L, top);
159
160 /* get package.preload */
161 lua_getglobal(L, "package"); lua_getfield(L, -1, "preload"); lua_remove(L, -2);
162 L_REGLIB(L, io, 1);
163 L_REGLIB(L, os, 1);
164 L_REGLIB(L, math, 1);
165 L_REGLIB(L, table, 1);
166 L_REGLIB(L, string, 1);
167
168#ifdef LUA_DBLIBNAME
169 L_REGLIB(L, debug, 1);
170#endif
171
172 /* @fixme find out luaopen_XXX at runtime */
173#ifdef LUA_JITLIBNAME
174 L_REGLIB(L, bit, 1);
175 L_REGLIB(L, jit, 1);
176 L_REGLIB(L, ffi, 1);
177#elif defined LUA_BITLIBNAME
178 L_REGLIB(L, bit32, 1);
179#endif
180
181#endif
182
183#ifdef LLTHREAD_REGISTER_THREAD_LIBRARY
184 L_REGLIB(L, llthreads, 0);
185#endif
186
187 lua_settop(L, top);
188
189#undef L_REGLIB
190}
191
192static llthread_child_t *llthread_child_new() {
193 llthread_child_t *this = ALLOC_STRUCT(llthread_child_t);
194 if(!this) return NULL;
195
196 memset(this, 0, sizeof(llthread_child_t));
197
198 /* create new lua_State for the thread. */
199 /* open standard libraries. */
200 this->L = luaL_newstate();
201 open_thread_libs(this->L);
202
203 return this;
204}
205
206static void llthread_child_destroy(llthread_child_t *this) {
207 lua_close(this->L);
208 FREE_STRUCT(this);
209}
210
211static OS_THREAD_RETURN llthread_child_thread_run(void *arg) {
212 llthread_child_t *this = (llthread_child_t *)arg;
213 lua_State *L = this->L;
214 int nargs = lua_gettop(L) - 1;
215
216 /* push traceback function as first value on stack. */
217 lua_pushcfunction(this->L, traceback);
218 lua_insert(L, 1);
219
220 this->status = lua_pcall(L, nargs, LUA_MULTRET, 1);
221
222 /* alwasy print errors here, helps with debugging bad code. */
223 if(this->status != 0) {
224 llthread_log(L, "Error from thread: ", lua_tostring(L, -1));
225 }
226
227 if(IS(this, DETACHED) || !IS(this, JOINABLE)) {
228 /* thread is detached, so it must clean-up the child state. */
229 llthread_child_destroy(this);
230 this = NULL;
231 }
232
233#ifndef USE_PTHREAD
234 if(this) {
235 /* attached thread, don't close thread handle. */
236 _endthreadex(0);
237 } else {
238 /* detached thread, close thread handle. */
239 _endthread();
240 }
241 return 0;
242#else
243 return this;
244#endif
245}
246
247//}
248
249//{ llthread
250
251static void llthread_validate(llthread_t *this){
252 /* describe valid state of llthread_t object
253 * from after create and before destroy
254 */
255 if(!IS(this, STARTED)){
256 assert(!IS(this, DETACHED));
257 assert(!IS(this, JOINED));
258 assert(!IS(this, JOINABLE));
259 return;
260 }
261
262 if(IS(this, DETACHED)){
263 if(!IS(this, JOINABLE)) assert(this->child == NULL);
264 else assert(this->child != NULL);
265 }
266}
267
268static int llthread_detach(llthread_t *this);
269
270static int llthread_join(llthread_t *this, join_timeout_t timeout);
271
272static llthread_t *llthread_new() {
273 llthread_t *this = ALLOC_STRUCT(llthread_t);
274 if(!this) return NULL;
275
276 this->flags = FLAG_NONE;
277#ifndef USE_PTHREAD
278 this->thread = INVALID_THREAD;
279#endif
280 this->child = llthread_child_new();
281 if(!this->child){
282 FREE_STRUCT(this);
283 return NULL;
284 }
285
286 return this;
287}
288
289static void llthread_cleanup_child(llthread_t *this) {
290 if(this->child) {
291 llthread_child_destroy(this->child);
292 this->child = NULL;
293 }
294}
295
296static void llthread_destroy(llthread_t *this) {
297 do{
298 /* thread not started */
299 if(!IS(this, STARTED)){
300 llthread_cleanup_child(this);
301 break;
302 }
303
304 /* DETACHED */
305 if(IS(this, DETACHED)){
306 if(IS(this, JOINABLE)){
307 llthread_detach(this);
308 }
309 break;
310 }
311
312 /* ATTACHED */
313 if(!IS(this, JOINED)){
314 llthread_join(this, INFINITE_JOIN_TIMEOUT);
315 if(!IS(this, JOINED)){
316 /* @todo use current lua state to logging */
317 /*
318 * char buf[ERROR_LEN];
319 * strerror_r(errno, buf, ERROR_LEN);
320 * llthread_log(L, "Error can not join thread on gc: ", buf);
321 */
322 }
323 }
324 if(IS(this, JOINABLE)){
325 llthread_cleanup_child(this);
326 }
327
328 }while(0);
329
330 FREE_STRUCT(this);
331}
332
333static int llthread_push_args(lua_State *L, llthread_child_t *child, int idx, int top) {
334 return llthread_copy_values(L, child->L, idx, top, 1 /* is_arg */);
335}
336
337static int llthread_push_results(lua_State *L, llthread_child_t *child, int idx, int top) {
338 return llthread_copy_values(child->L, L, idx, top, 0 /* is_arg */);
339}
340
341static int llthread_detach(llthread_t *this){
342 int rc = 0;
343
344 assert(IS(this, STARTED));
345 assert(this->child != NULL);
346
347 this->child = NULL;
348
349 /*we can not detach joined thread*/
350 if(IS(this, JOINED))
351 return 0;
352
353#ifdef USE_PTHREAD
354 rc = pthread_detach(this->thread);
355#else
356 assert(this->thread != INVALID_THREAD);
357 CloseHandle(this->thread);
358 this->thread = INVALID_THREAD;
359#endif
360 return rc;
361}
362
363/* | detached | joinable || join | which thread | gc | detach |
364 * | | || return | destroy child | calls | on |
365 * ------------------------------------------------------------------------
366 * | false | falas || <NONE> | child | join | <NEVER> |
367 * *| false | true || Lua values | parent | join | <NEVER> |
368 * *| true | false || <ERROR> | child | <NONE> | start |
369 * | true | true || <NONE> | child | detach | gc |
370 * ------------------------------------------------------------------------
371 * * llthread behavior.
372 */
373static int llthread_start(llthread_t *this, int start_detached, int joinable) {
374 llthread_child_t *child = this->child;
375 int rc = 0;
376
377 llthread_validate(this);
378
379 if(joinable) SET(child, JOINABLE);
380 if(start_detached) SET(child, DETACHED);
381
382#ifndef USE_PTHREAD
383 this->thread = (HANDLE)_beginthreadex(NULL, 0, llthread_child_thread_run, child, 0, NULL);
384 if(INVALID_THREAD == this->thread){
385 rc = -1;
386 }
387#else
388 rc = pthread_create(&(this->thread), NULL, llthread_child_thread_run, child);
389#endif
390
391 if(rc == 0) {
392 SET(this, STARTED);
393 if(joinable) SET(this, JOINABLE);
394 if(start_detached) SET(this, DETACHED);
395 if((start_detached)&&(!joinable)){
396 rc = llthread_detach(this);
397 }
398 }
399
400 llthread_validate(this);
401
402 return rc;
403}
404
405static int llthread_join(llthread_t *this, join_timeout_t timeout) {
406 llthread_validate(this);
407
408 if(IS(this, JOINED)){
409 return JOIN_OK;
410 } else{
411#ifndef USE_PTHREAD
412 DWORD ret = 0;
413 if(INVALID_THREAD == this->thread) return JOIN_OK;
414 ret = WaitForSingleObject( this->thread, timeout );
415 if( ret == WAIT_OBJECT_0){ /* Destroy the thread object. */
416 CloseHandle( this->thread );
417 this->thread = INVALID_THREAD;
418 SET(this, JOINED);
419
420 llthread_validate(this);
421
422 return JOIN_OK;
423 }
424 else if( ret == WAIT_TIMEOUT ){
425 return JOIN_ETIMEDOUT;
426 }
427 return JOIN_FAIL;
428#else
429 int rc;
430 if(timeout == 0){
431 rc = pthread_kill(this->thread, 0);
432 if(rc == 0){ /* still alive */
433 return JOIN_ETIMEDOUT;
434 }
435
436 if(rc != ESRCH){
437 /*@fixme what else it can be ?*/
438 return rc;
439 }
440
441 /*thread dead so we call join to free pthread_t struct */
442 }
443
444 /* @todo use pthread_tryjoin_np/pthread_timedjoin_np to support timeout */
445
446 /* then join the thread. */
447 rc = pthread_join(this->thread, NULL);
448 if((rc == 0) || (rc == ESRCH)) {
449 SET(this, JOINED);
450 rc = JOIN_OK;
451 }
452
453 llthread_validate(this);
454
455 return rc;
456#endif
457 }
458}
459
460static int llthread_alive(llthread_t *this) {
461 llthread_validate(this);
462
463 if(IS(this, JOINED)){
464 return JOIN_OK;
465 } else{
466#ifndef USE_PTHREAD
467 DWORD ret = 0;
468 if(INVALID_THREAD == this->thread) return JOIN_OK;
469 ret = WaitForSingleObject( this->thread, 0 );
470 if( ret == WAIT_OBJECT_0) return JOIN_OK;
471 if( ret == WAIT_TIMEOUT ) return JOIN_ETIMEDOUT;
472 return JOIN_FAIL;
473#else
474 int rc = pthread_kill(this->thread, 0);
475 if(rc == 0){ /* still alive */
476 return JOIN_ETIMEDOUT;
477 }
478
479 if(rc != ESRCH){
480 /*@fixme what else it can be ?*/
481 return rc;
482 }
483
484 return JOIN_OK;
485#endif
486 }
487}
488
489static llthread_t *llthread_create(lua_State *L, const char *code, size_t code_len) {
490 llthread_t *this = llthread_new();
491 llthread_child_t *child = this->child;
492
493 /* load Lua code into child state. */
494 int rc = luaL_loadbuffer(child->L, code, code_len, code);
495 if(rc != 0) {
496 /* copy error message to parent state. */
497 size_t len; const char *str = lua_tolstring(child->L, -1, &len);
498 if(str != NULL) {
499 lua_pushlstring(L, str, len);
500 } else {
501 /* non-string error message. */
502 lua_pushfstring(L, "luaL_loadbuffer() failed to load Lua code: rc=%d", rc);
503 }
504 llthread_destroy(this);
505 lua_error(L);
506 return NULL;
507 }
508
509 /* copy extra args from main state to child state. */
510 /* Push all args after the Lua code. */
511 llthread_push_args(L, child, 3, lua_gettop(L));
512
513 llthread_validate(this);
514
515 return this;
516}
517
518//}
519
520//{ Lua interface to llthread
521
522static llthread_t *l_llthread_at (lua_State *L, int i) {
523 llthread_t **this = (llthread_t **)lutil_checkudatap (L, i, LLTHREAD_TAG);
524 luaL_argcheck (L, this != NULL, i, "thread expected");
525 luaL_argcheck (L, *this != NULL, i, "thread expected");
526 // luaL_argcheck (L, !(counter->flags & FLAG_DESTROYED), 1, "PDH Counter is destroyed");
527 return *this;
528}
529
530static int l_llthread_delete(lua_State *L) {
531 llthread_t **pthis = (llthread_t **)lutil_checkudatap (L, 1, LLTHREAD_TAG);
532 luaL_argcheck (L, pthis != NULL, 1, "thread expected");
533 if(*pthis == NULL) return 0;
534 llthread_destroy(*pthis);
535 *pthis = NULL;
536
537 return 0;
538}
539
540static int l_llthread_start(lua_State *L) {
541 llthread_t *this = l_llthread_at(L, 1);
542 int start_detached = lua_toboolean(L, 2);
543 int joinable, rc;
544
545 if(!lua_isnone(L, 3)) joinable = lua_toboolean(L, 3);
546 else joinable = start_detached ? 0 : 1;
547
548 if(IS(this, STARTED)) {
549 return fail(L, "Thread already started.");
550 }
551
552 rc = llthread_start(this, start_detached, joinable);
553 if(rc != 0) {
554 char buf[ERROR_LEN];
555 strerror_r(errno, buf, ERROR_LEN);
556 return fail(L, buf);
557 }
558
559 lua_settop(L, 1); // return this
560 return 1;
561}
562
563static int l_llthread_join(lua_State *L) {
564 llthread_t *this = l_llthread_at(L, 1);
565 llthread_child_t *child = this->child;
566 int rc;
567
568 if(!IS(this, STARTED )) {
569 return fail(L, "Can't join a thread that hasn't be started.");
570 }
571 if( IS(this, DETACHED) && !IS(this, JOINABLE)) {
572 return fail(L, "Can't join a thread that has been detached.");
573 }
574 if( IS(this, JOINED )) {
575 return fail(L, "Can't join a thread that has already been joined.");
576 }
577
578 /* join the thread. */
579 rc = llthread_join(this, luaL_optint(L, 2, INFINITE_JOIN_TIMEOUT));
580
581 if(child && IS(this, JOINED)) {
582 int top;
583
584 if(IS(this, DETACHED) || !IS(this, JOINABLE)){
585 /*child lua state has been destroyed by child thread*/
586 /*@todo return thread exit code*/
587 lua_pushboolean(L, 1);
588 lua_pushnumber(L, 0);
589 return 2;
590 }
591
592 /* copy values from child lua state */
593 if(child->status != 0) {
594 const char *err_msg = lua_tostring(child->L, -1);
595 lua_pushboolean(L, 0);
596 lua_pushfstring(L, "Error from child thread: %s", err_msg);
597 top = 2;
598 } else {
599 lua_pushboolean(L, 1);
600 top = lua_gettop(child->L);
601 /* return results to parent thread. */
602 llthread_push_results(L, child, 2, top);
603 }
604
605 llthread_cleanup_child(this);
606 return top;
607 }
608
609 if( rc == JOIN_ETIMEDOUT ){
610 return fail(L, "timeout");
611 }
612
613 {
614 char buf[ERROR_LEN];
615 strerror_r(errno, buf, ERROR_LEN);
616
617 /* llthread_cleanup_child(this); */
618
619 return fail(L, buf);
620 }
621
622}
623
624static int l_llthread_alive(lua_State *L) {
625 llthread_t *this = l_llthread_at(L, 1);
626 llthread_child_t *child = this->child;
627 int rc;
628
629 if(!IS(this, STARTED )) {
630 return fail(L, "Can't join a thread that hasn't be started.");
631 }
632 if( IS(this, DETACHED) && !IS(this, JOINABLE)) {
633 return fail(L, "Can't join a thread that has been detached.");
634 }
635 if( IS(this, JOINED )) {
636 return fail(L, "Can't join a thread that has already been joined.");
637 }
638
639 /* join the thread. */
640 rc = llthread_alive(this);
641
642 if( rc == JOIN_ETIMEDOUT ){
643 lua_pushboolean(L, 1);
644 return 1;
645 }
646
647 if(rc == JOIN_OK){
648 lua_pushboolean(L, 0);
649 return 1;
650 }
651
652 {
653 char buf[ERROR_LEN];
654 strerror_r(errno, buf, ERROR_LEN);
655
656 /* llthread_cleanup_child(this); */
657
658 return fail(L, buf);
659 }
660
661}
662
663static int l_llthread_new(lua_State *L) {
664 size_t lua_code_len; const char *lua_code = luaL_checklstring(L, 1, &lua_code_len);
665 llthread_t **this = lutil_newudatap(L, llthread_t*, LLTHREAD_TAG);
666 lua_insert(L, 2); /*move self prior args*/
667 *this = llthread_create(L, lua_code, lua_code_len);
668
669 lua_settop(L, 2);
670 return 1;
671}
672
673static const struct luaL_Reg l_llthread_meth[] = {
674 {"start", l_llthread_start },
675 {"join", l_llthread_join },
676 {"alive", l_llthread_alive },
677 {"__gc", l_llthread_delete },
678
679 {NULL, NULL}
680};
681
682//}
683
684//{ version
685
686static int l_llthread_version(lua_State *L){
687 lua_pushnumber(L, LLTHREAD_VERSION_MAJOR);
688 lua_pushnumber(L, LLTHREAD_VERSION_MINOR);
689 lua_pushnumber(L, LLTHREAD_VERSION_PATCH);
690#ifdef LLTHREAD_VERSION_COMMENT
691 if(LLTHREAD_VERSION_COMMENT[0]){
692 lua_pushliteral(L, LLTHREAD_VERSION_COMMENT);
693 return 4;
694 }
695#endif
696 return 3;
697}
698
699static int l_llthread_push_version(lua_State *L){
700 lua_pushnumber(L, LLTHREAD_VERSION_MAJOR);
701 lua_pushliteral(L, ".");
702 lua_pushnumber(L, LLTHREAD_VERSION_MINOR);
703 lua_pushliteral(L, ".");
704 lua_pushnumber(L, LLTHREAD_VERSION_PATCH);
705#ifdef LLTHREAD_VERSION_COMMENT
706 if(LLTHREAD_VERSION_COMMENT[0]){
707 lua_pushliteral(L, "-"LLTHREAD_VERSION_COMMENT);
708 lua_concat(L, 6);
709 }
710 else
711#endif
712 lua_concat(L, 5);
713 return 1;
714}
715
716//}
717
718static int l_llthread_set_logger(lua_State *L){
719 lua_settop(L, 1);
720 luaL_argcheck(L, lua_isfunction(L, 1), 1, "function expected");
721 lua_rawsetp(L, LUA_REGISTRYINDEX, LLTHREAD_LOGGER_HOLDER);
722 return 0;
723}
724
725static const struct luaL_Reg l_llthreads_lib[] = {
726 {"new", l_llthread_new },
727 {"set_logger", l_llthread_set_logger },
728 {"version", l_llthread_version },
729
730 {NULL, NULL}
731};
732
733LLTHREADS_EXPORT_API int LLTHREAD_OPEN_NAME(lua_State *L) {
734 int top = lua_gettop(L);
735 lutil_createmetap(L, LLTHREAD_TAG, l_llthread_meth, 0);
736 lua_settop(L, top);
737
738 lua_newtable(L);
739 luaL_setfuncs(L, l_llthreads_lib, 0);
740
741 lua_pushliteral(L, "_VERSION");
742 l_llthread_push_version(L);
743 lua_rawset(L, -3);
744
745 return 1;
746}
diff --git a/llthreads2/src/traceback.inc b/llthreads2/src/traceback.inc
new file mode 100644
index 0000000..af2f5a1
--- /dev/null
+++ b/llthreads2/src/traceback.inc
@@ -0,0 +1,56 @@
1/******************************************************************************
2* traceback() function from Lua 5.1/5.2 source.
3* Copyright (C) 1994-2008 Lua.org, PUC-Rio. All rights reserved.
4*
5* Permission is hereby granted, free of charge, to any person obtaining
6* a copy of this software and associated documentation files (the
7* "Software"), to deal in the Software without restriction, including
8* without limitation the rights to use, copy, modify, merge, publish,
9* distribute, sublicense, and/or sell copies of the Software, and to
10* permit persons to whom the Software is furnished to do so, subject to
11* the following conditions:
12*
13* The above copyright notice and this permission notice shall be
14* included in all copies or substantial portions of the Software.
15*
16* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23******************************************************************************/
24#if !defined(LUA_VERSION_NUM) || (LUA_VERSION_NUM == 501)
25/* from Lua 5.1 */
26static int traceback (lua_State *L) {
27 if (!lua_isstring(L, 1)) /* 'message' not a string? */
28 return 1; /* keep it intact */
29 lua_getglobal(L, "debug");
30 if (!lua_istable(L, -1)) {
31 lua_pop(L, 1);
32 return 1;
33 }
34 lua_getfield(L, -1, "traceback");
35 if (!lua_isfunction(L, -1)) {
36 lua_pop(L, 2);
37 return 1;
38 }
39 lua_pushvalue(L, 1); /* pass error message */
40 lua_pushinteger(L, 2); /* skip this function and traceback */
41 lua_call(L, 2, 1); /* call debug.traceback */
42 return 1;
43}
44#else
45/* from Lua 5.2 */
46static int traceback (lua_State *L) {
47 const char *msg = lua_tostring(L, 1);
48 if (msg)
49 luaL_traceback(L, L, msg, 1);
50 else if (!lua_isnoneornil(L, 1)) { /* is there an error object? */
51 if (!luaL_callmeta(L, 1, "__tostring")) /* try its 'tostring' metamethod */
52 lua_pushliteral(L, "(no error message)");
53 }
54 return 1;
55}
56#endif
diff --git a/llthreads2/test/test_alive.lua b/llthreads2/test/test_alive.lua
new file mode 100644
index 0000000..ecce163
--- /dev/null
+++ b/llthreads2/test/test_alive.lua
@@ -0,0 +1,35 @@
1local llthreads = require"llthreads"
2local utils = require "utils"
3local sleep = utils.sleep
4
5local include = utils.thread_init .. [[
6local llthreads = require"llthreads"
7local sleep = require "utils".sleep
8]]
9
10local thread = llthreads.new(include .. [[
11 sleep(5)
12 return 1,2,3
13]])
14
15assert(nil == thread:alive())
16
17thread:start()
18
19assert(true == thread:alive())
20
21for i = 1, 10 do
22 if not thread:alive() then break end
23 sleep(1)
24end
25
26assert(false == thread:alive())
27
28local ok,a,b,c = thread:join(0)
29assert(ok == true)
30assert(a == 1)
31assert(b == 2)
32assert(c == 3)
33
34print("Done!")
35
diff --git a/llthreads2/test/test_join_detach.lua b/llthreads2/test/test_join_detach.lua
new file mode 100644
index 0000000..533a36f
--- /dev/null
+++ b/llthreads2/test/test_join_detach.lua
@@ -0,0 +1,59 @@
1local llthreads = require"llthreads"
2local utils = require "utils"
3
4do
5
6local thread = llthreads.new(utils.thread_init .. [[
7 local sleep = require"utils".sleep
8 while true do sleep(1) end
9]])
10
11-- detached + joindable
12thread:start(true, true)
13
14local ok, err = thread:join(0)
15print("thread:join(0): ", ok, err)
16assert(ok == nil)
17assert(err == "timeout")
18
19end
20
21-- enforce collect `thread` object
22-- we should not hungup
23for i = 1, 10 do collectgarbage("collect") end
24
25
26do
27
28local thread = llthreads.new(utils.thread_init .. [[
29 local sleep = require"utils".sleep
30 sleep(1)
31]])
32
33-- detached + joindable
34thread:start(true, true)
35
36local ok, err = thread:join(0)
37print("thread:join(0): ", ok, err)
38assert(ok == nil)
39assert(err == "timeout")
40
41for i = 1, 12 do
42 utils.sleep(5)
43 ok, err = thread:join(0)
44 print("thread:join(0)#" .. i .. ": ", ok, err)
45 if ok then break end
46 assert(err == 'timeout')
47end
48
49assert(ok)
50
51end
52
53-- enforce collect `thread` object
54-- we should not get av
55for i = 1, 10 do collectgarbage("collect") end
56
57
58print("Done!")
59
diff --git a/llthreads2/test/test_join_error.lua b/llthreads2/test/test_join_error.lua
new file mode 100644
index 0000000..90780b1
--- /dev/null
+++ b/llthreads2/test/test_join_error.lua
@@ -0,0 +1,24 @@
1local llthreads = require "llthreads"
2local utils = require "utils"
3local sleep = utils.sleep
4
5local include = utils.thread_init .. [[
6local llthreads = require"llthreads"
7local sleep = require "utils".sleep
8]]
9
10local thread = llthreads.new(include .. [[
11 sleep(5)
12]])
13
14thread:start()
15
16local ok, err = thread:join()
17assert(ok == true)
18assert(err == nil)
19
20local res, ok, err = pcall(thread.join, thread)
21assert(res == true)
22assert(ok == nil)
23assert(err ~= nil)
24
diff --git a/llthreads2/test/test_join_timeout.lua b/llthreads2/test/test_join_timeout.lua
new file mode 100644
index 0000000..b9cf155
--- /dev/null
+++ b/llthreads2/test/test_join_timeout.lua
@@ -0,0 +1,23 @@
1local llthreads = require"llthreads"
2local utils = require "utils"
3local sleep = utils.sleep
4
5local include = utils.thread_init .. [[
6local llthreads = require"llthreads"
7local sleep = require "utils".sleep
8]]
9
10local thread = llthreads.new(include .. [[
11 sleep(5)
12]])
13thread:start()
14local ok, err = thread:join(0)
15print("thread:join(0): ", ok, err)
16assert(ok == nil)
17assert(err == "timeout")
18
19local ok, err = thread:join()
20print("thread:join(): ", ok, err)
21assert(ok, err)
22print("Done!")
23
diff --git a/llthreads2/test/test_llthreads.lua b/llthreads2/test/test_llthreads.lua
new file mode 100644
index 0000000..e0e214b
--- /dev/null
+++ b/llthreads2/test/test_llthreads.lua
@@ -0,0 +1,60 @@
1-- Copyright (c) 2011 by Robert G. Jakabosky <bobby@sharedrealm.com>
2--
3-- Permission is hereby granted, free of charge, to any person obtaining a copy
4-- of this software and associated documentation files (the "Software"), to deal
5-- in the Software without restriction, including without limitation the rights
6-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7-- copies of the Software, and to permit persons to whom the Software is
8-- furnished to do so, subject to the following conditions:
9--
10-- The above copyright notice and this permission notice shall be included in
11-- all copies or substantial portions of the Software.
12--
13-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19-- THE SOFTWARE.
20
21local llthreads = require"llthreads"
22local sleep = require"utils".sleep
23
24print("LLThreads version : ", llthreads._VERSION)
25
26local function detached_thread(...)
27 local thread = llthreads.new([[ print("print_detached_thread:", ...) ]], ...)
28 -- start detached thread
29 assert(thread:start(true))
30 return thread
31end
32
33local function print_thread(...)
34 local thread = llthreads.new([[ print("print_thread:", ...); ]], ...)
35 -- start joinable thread
36 assert(thread:start())
37 return thread
38end
39
40local function pass_through_thread(...)
41 local thread = llthreads.new([[ return "pass_thread:", ... ]], ...)
42 -- start joinable thread
43 assert(thread:start())
44 return thread
45end
46
47local thread1 = detached_thread("number:", 1234, "nil:", nil, "bool:", true)
48
49sleep(1)
50
51local thread2 = print_thread("number:", 1234, "nil:", nil, "bool:", true)
52print("thread2:join: results # = ", select('#', thread2:join()))
53
54sleep(1)
55
56local thread3 = pass_through_thread("number:", 1234, "nil:", nil, "bool:", true)
57print("thread3:join:", thread3:join())
58
59sleep(1)
60
diff --git a/llthreads2/test/test_load_llthreads2.lua b/llthreads2/test/test_load_llthreads2.lua
new file mode 100644
index 0000000..11bf0a0
--- /dev/null
+++ b/llthreads2/test/test_load_llthreads2.lua
@@ -0,0 +1,7 @@
1local llthreads = require"llthreads2"
2
3llthreads.new([[
4 local os = require "os"
5 print("Done!")
6 os.exit(0)
7]]):start():join() \ No newline at end of file
diff --git a/llthreads2/test/test_logger.lua b/llthreads2/test/test_logger.lua
new file mode 100644
index 0000000..f85a896
--- /dev/null
+++ b/llthreads2/test/test_logger.lua
@@ -0,0 +1,24 @@
1local utils = require "utils"
2
3require "llthreads".new(utils.thread_init .. [[
4require "string"
5
6require "llthreads".set_logger(function(msg)
7 if type(msg) ~= 'string' then
8 print("ERROR! Invalid error message: ", msg)
9 os.exit(-2)
10 end
11 if not msg:find("SOME ERROR", nil, true) then
12 print("ERROR! Invalid error message: ", msg)
13 os.exit(-1)
14 end
15 print("Done!")
16 os.exit(0)
17end)
18
19error("SOME ERROR")
20]]):start():join()
21
22print("ERROR! Logger has not been call!")
23os.exit(-1)
24
diff --git a/llthreads2/test/test_pass_cfunction.lua b/llthreads2/test/test_pass_cfunction.lua
new file mode 100644
index 0000000..86fcd3d
--- /dev/null
+++ b/llthreads2/test/test_pass_cfunction.lua
@@ -0,0 +1,17 @@
1local llthreads = require"llthreads"
2local utils = require"utils"
3
4local thread = llthreads.new(utils.thread_init .. [[
5 require "llthreads"
6 local fn = ...
7
8 if type(fn) ~= 'function' then
9 print("ERROR! No function : ", fn, type(fn))
10 os.exit(-2)
11 end
12
13 fn("print('Done!'); require'os'.exit(0)"):start():join()
14]], llthreads.new)
15
16print(thread:start():join())
17os.exit(-1) \ No newline at end of file
diff --git a/llthreads2/test/test_register_ffi.lua b/llthreads2/test/test_register_ffi.lua
new file mode 100644
index 0000000..e98167f
--- /dev/null
+++ b/llthreads2/test/test_register_ffi.lua
@@ -0,0 +1,14 @@
1if jit then
2 local llthreads = require "llthreads"
3 local thread = llthreads.new([[
4 if not package.preload.ffi then
5 print("ffi does not register in thread")
6 os.exit(-1)
7 end
8 local ok, err = pcall(require, "ffi")
9 if not ok then
10 print("can not load ffi: ", err)
11 os.exit(-2)
12 end
13 ]]):start():join()
14end
diff --git a/llthreads2/test/test_register_llthreads.lua b/llthreads2/test/test_register_llthreads.lua
new file mode 100644
index 0000000..5b234a9
--- /dev/null
+++ b/llthreads2/test/test_register_llthreads.lua
@@ -0,0 +1,15 @@
1-- Test if you build module with
2-- LLTHREAD_REGISTER_THREAD_LIBRARY
3
4local llthreads = require "llthreads"
5local thread = llthreads.new([[
6 if not package.preload.llthreads then
7 print("llthreads does not register in thread")
8 os.exit(-1)
9 end
10 local ok, err = pcall(require, "llthreads")
11 if not ok then
12 print("can not load llthreads: ", err)
13 os.exit(-2)
14 end
15]]):start():join()
diff --git a/llthreads2/test/test_table_copy.lua b/llthreads2/test/test_table_copy.lua
new file mode 100644
index 0000000..0408ad3
--- /dev/null
+++ b/llthreads2/test/test_table_copy.lua
@@ -0,0 +1,134 @@
1-- Copyright (c) 2011 by Robert G. Jakabosky <bobby@sharedrealm.com>
2--
3-- Permission is hereby granted, free of charge, to any person obtaining a copy
4-- of this software and associated documentation files (the "Software"), to deal
5-- in the Software without restriction, including without limitation the rights
6-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7-- copies of the Software, and to permit persons to whom the Software is
8-- furnished to do so, subject to the following conditions:
9--
10-- The above copyright notice and this permission notice shall be included in
11-- all copies or substantial portions of the Software.
12--
13-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19-- THE SOFTWARE.
20
21local llthreads = require"llthreads"
22
23local sleep
24local status, socket = pcall(require,"socket")
25if status then
26 sleep = function(secs)
27 return socket.sleep(secs)
28 end
29else
30 sleep = function(secs)
31 os.execute("sleep " .. tonumber(secs))
32 end
33end
34
35local dump_code = [==[
36local function dump_recur(seen, obj, depth)
37 local out
38 local t = type(obj)
39 -- if not a table just convert to string.
40 if t ~= "table" then
41 if t == "string" then
42 return '"' .. obj .. '"'
43 end
44 return tostring(obj)
45 end
46 -- check if this table has been seen already.
47 if seen[obj] then
48 return "Already dumped " .. tostring(obj)
49 end
50 seen[obj] = true
51 -- restrict max depth.
52 if depth >= 10 then
53 return "{... max depth reached ...}"
54 end
55 depth = depth + 1
56 -- output table key/value pairs
57 local tabs = string.rep(" ",depth)
58 local out = "{\n"
59 for k,v in pairs(obj) do
60 if type(k) ~= "number" then
61 out = out .. tabs .. '[' .. dump_recur(seen, k, depth) .. '] = ' ..
62 dump_recur(seen, v, depth) .. ',\n'
63 else
64 out = out .. tabs .. '[' .. k .. '] = ' .. dump_recur(seen, v, depth) .. ',\n'
65 end
66 end
67 return out .. tabs:sub(1,-3) .. "}"
68end
69
70local obj = ...
71local seen = {}
72return dump_recur(seen, obj, 0)
73]==]
74
75local dump = (loadstring or load)(dump_code)
76
77local child_code = [==[
78local dump = (loadstring or load)[[
79]==] .. dump_code .. [==[
80]]
81local args = ...
82
83print("Child thread args:", dump(args))
84
85-- return all values.
86return ...
87]==]
88
89local function test_thread_value_copying(...)
90 local args = {...}
91 print("Main thread args:", dump(args))
92 local thread = llthreads.new(child_code, args)
93 -- start joinable thread
94 assert(thread:start())
95
96 local status, results = thread:join()
97 print("Main thread results:", dump(results))
98end
99
100-- create some tables.
101local a1 = { "a1" }
102local a2 = { "a2" }
103local a3 = { "a3" }
104local a4 = { "a4" }
105local b1 = { a1, a2, a3, a4 }
106local b2 = { a1=a1, a2=a2, a3=a3, a4=a4 }
107
108--
109-- no loops
110--
111test_thread_value_copying(b1, b2)
112
113local top = {}
114-- self reference.
115top.top = top
116top[top] = top
117-- nested reference.
118top.sub1 = { sub2 = { sub3 = { top } } }
119
120--
121-- loops
122--
123test_thread_value_copying(top)
124
125--
126-- Test max depth
127--
128local outer = {}
129for n=1,100 do
130 outer = {outer}
131end
132local status, err = pcall(test_thread_value_copying,outer)
133assert(not status, "Assertion failed: max depth test failed.")
134
diff --git a/llthreads2/test/test_threads.lua b/llthreads2/test/test_threads.lua
new file mode 100644
index 0000000..459604d
--- /dev/null
+++ b/llthreads2/test/test_threads.lua
@@ -0,0 +1,67 @@
1-- Copyright (c) 2011 by Ross Anderson <ross_j_anderson@yahoo.com>
2--
3-- Permission is hereby granted, free of charge, to any person obtaining a copy
4-- of this software and associated documentation files (the "Software"), to deal
5-- in the Software without restriction, including without limitation the rights
6-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7-- copies of the Software, and to permit persons to whom the Software is
8-- furnished to do so, subject to the following conditions:
9--
10-- The above copyright notice and this permission notice shall be included in
11-- all copies or substantial portions of the Software.
12--
13-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19-- THE SOFTWARE.
20
21-- Sub-thread processing example in Lua using llthreads - 1,000 quick sub-thread execution
22
23-- luajit sub_threads.lua
24
25local llthreads = require"llthreads"
26local utils = require "utils"
27
28local num_threads = tonumber(arg[1] or 1000)
29
30-- level 0 string literal enclosure [[ ]] of child execution code
31local thread_code = utils.thread_init .. [[
32
33 local num_threads = ...
34 print("CHILD: received from ROOT params:", ...)
35 local llthreads = require"llthreads" -- need to re-declare this under this scope
36 local t = {} -- thread storage table
37
38 -- create a new child sub-thread execution code - it requires level 1 literal string [=[ ]=] enclosures, level 2 would be [==[ ]==]
39 local executed_child_code = [=[
40 return "Hello from child sub-thread, new input params:", ...
41 ]=]
42
43 -- create 1000 sub-threads - which creates an incremental 30% / 20% utilization spike on the two AMD cpu cores
44 print("CHILD: Create sub threads:", num_threads)
45 for i=1,num_threads do
46 -- create child sub-thread with code to execute and the input parmeters
47 local thread = llthreads.new(executed_child_code , "number:", 1000 + i, "nil:", nil, "bool:", true)
48 assert(thread:start()) -- start new child sub-thread
49 table.insert(t, thread) -- append the thread at the end of the thread table
50 end
51
52 -- wait (block) for all child sub-threads to complete before returning to ROOT
53 while true do
54 -- always wait on the first element, since order is not important
55 print("CHILD: sub-thread returned: ", t[1]:join())
56 table.remove(t,1) -- always remove the first element
57 if (#t == 0) then break end
58 end
59 return ... -- return the parents' input params back to the root
60]]
61
62-- create child thread.
63local thread = llthreads.new(thread_code, num_threads, "number:", 1000, "nil:", nil, "bool:", true)
64-- start joinable child thread.
65assert(thread:start())
66-- wait for all child and child sub-threads to finish
67print("ROOT: child returned: ", thread:join())
diff --git a/llthreads2/test/utils.lua b/llthreads2/test/utils.lua
new file mode 100644
index 0000000..d9b5fe5
--- /dev/null
+++ b/llthreads2/test/utils.lua
@@ -0,0 +1,63 @@
1local lua_version_t
2local function lua_version()
3 if not lua_version_t then
4 local version = rawget(_G,"_VERSION")
5 local maj,min = version:match("^Lua (%d+)%.(%d+)$")
6 if maj then lua_version_t = {tonumber(maj),tonumber(min)}
7 elseif not math.mod then lua_version_t = {5,2}
8 elseif table.pack and not pack then lua_version_t = {5,2}
9 else lua_version_t = {5,2} end
10 end
11 return lua_version_t[1], lua_version_t[2]
12end
13
14local LUA_MAJOR, LUA_MINOR = lua_version()
15local IS_LUA_51 = (LUA_MAJOR == 5) and (LUA_MINOR == 1)
16local IS_LUA_52 = (LUA_MAJOR == 5) and (LUA_MINOR == 2)
17
18local LUA_INIT = "LUA_INIT"
19local LUA_INIT_VER
20if not IS_LUA_51 then
21 LUA_INIT_VER = LUA_INIT .. "_" .. LUA_MAJOR .. "_" .. LUA_MINOR
22end
23
24LUA_INIT = LUA_INIT_VER and os.getenv( LUA_INIT_VER ) or os.getenv( LUA_INIT ) or ""
25
26LUA_INIT = [[do
27 local lua_init = ]] .. ("%q"):format(LUA_INIT) .. [[
28 if lua_init and #lua_init > 0 then
29 if lua_init:sub(1,1) == '@' then
30 dofile(lua_init:sub(2))
31 else
32 assert((loadstring or load)(lua_init))()
33 end
34 end
35end;]]
36
37local sleep
38local status, socket = pcall(require,"socket")
39if status then
40 sleep = function(secs)
41 return socket.sleep(secs)
42 end
43end
44
45if not sleep then
46 local status, ztimer = pcall(require, "lzmq.timer")
47 if status then
48 sleep = function(secs)
49 ztimer.sleep(secs * 1000)
50 end
51 end
52end
53
54if not sleep then
55 sleep = function(secs)
56 os.execute("sleep " .. tonumber(secs))
57 end
58end
59
60return {
61 thread_init = LUA_INIT,
62 sleep = sleep,
63}