Merge pull request #1266 from alliedmodders/threads-3
Pare down ThreadSupport and remove ancient thread code.
This commit is contained in:
		
						commit
						15023777f4
					
				
							
								
								
									
										128
									
								
								.travis.yml
									
									
									
									
									
								
							
							
						
						
									
										128
									
								
								.travis.yml
									
									
									
									
									
								
							@ -3,110 +3,80 @@ git:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
sudo: false
 | 
					sudo: false
 | 
				
			||||||
language: cpp
 | 
					language: cpp
 | 
				
			||||||
os: linux
 | 
					 | 
				
			||||||
dist: trusty
 | 
					 | 
				
			||||||
addons:
 | 
					 | 
				
			||||||
  apt:
 | 
					 | 
				
			||||||
    sources:
 | 
					 | 
				
			||||||
      - ubuntu-toolchain-r-test
 | 
					 | 
				
			||||||
      - llvm-toolchain-trusty-3.9
 | 
					 | 
				
			||||||
      - llvm-toolchain-trusty-4.0
 | 
					 | 
				
			||||||
      - llvm-toolchain-trusty-5.0
 | 
					 | 
				
			||||||
    packages:
 | 
					 | 
				
			||||||
      - lib32stdc++6
 | 
					 | 
				
			||||||
      - lib32z1-dev
 | 
					 | 
				
			||||||
      - libc6-dev-i386
 | 
					 | 
				
			||||||
      - linux-libc-dev
 | 
					 | 
				
			||||||
      - g++-multilib
 | 
					 | 
				
			||||||
#      - clang-3.6
 | 
					 | 
				
			||||||
#      - clang-3.8
 | 
					 | 
				
			||||||
#      - clang-4.0
 | 
					 | 
				
			||||||
#      - clang-5.0
 | 
					 | 
				
			||||||
#      - g++-6
 | 
					 | 
				
			||||||
#      - g++-6-multilib
 | 
					 | 
				
			||||||
      - clang-3.9
 | 
					 | 
				
			||||||
      - g++-4.8-multilib
 | 
					 | 
				
			||||||
      - g++-4.8
 | 
					 | 
				
			||||||
      - g++-4.9-multilib
 | 
					 | 
				
			||||||
      - g++-4.9
 | 
					 | 
				
			||||||
      - g++-5-multilib
 | 
					 | 
				
			||||||
      - g++-5
 | 
					 | 
				
			||||||
      - g++-7-multilib
 | 
					 | 
				
			||||||
      - g++-7
 | 
					 | 
				
			||||||
    cache:
 | 
					 | 
				
			||||||
      directories:
 | 
					 | 
				
			||||||
        - ../mysql-5.0
 | 
					 | 
				
			||||||
env:
 | 
					 | 
				
			||||||
 - MATRIX_EVAL="CC=clang-3.9 && CXX=clang++-3.9"
 | 
					 | 
				
			||||||
 - MATRIX_EVAL="CC=gcc-4.8 && CXX=g++-4.8"
 | 
					 | 
				
			||||||
 - MATRIX_EVAL="CC=gcc-4.9 && CXX=g++-4.9"
 | 
					 | 
				
			||||||
 - MATRIX_EVAL="CC=gcc-5 && CXX=g++-5"
 | 
					 | 
				
			||||||
 - MATRIX_EVAL="CC=gcc-7 && CXX=g++-7"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
matrix:
 | 
					matrix:
 | 
				
			||||||
  fast_finish: true
 | 
					  fast_finish: true
 | 
				
			||||||
  include:
 | 
					  include:
 | 
				
			||||||
    - os: linux
 | 
					    - os: linux
 | 
				
			||||||
 | 
					      dist: trusty
 | 
				
			||||||
      sudo: false
 | 
					      sudo: false
 | 
				
			||||||
      language: cpp
 | 
					      language: cpp
 | 
				
			||||||
      addons:
 | 
					      addons:
 | 
				
			||||||
        apt:
 | 
					        apt:
 | 
				
			||||||
          packages: ['clang-3.6', 'lib32stdc++6', 'lib32z1-dev', 'libc6-dev-i386', 'linux-libc-dev', 'g++-multilib']
 | 
					          sources:
 | 
				
			||||||
 | 
					            - ubuntu-toolchain-r-test
 | 
				
			||||||
 | 
					          packages: ['clang-3.8', 'lib32stdc++6', 'lib32z1-dev', 'libc6-dev-i386', 'linux-libc-dev:i386', 'g++-4.9-multilib']
 | 
				
			||||||
        cache:
 | 
					        cache:
 | 
				
			||||||
          directories: ['../mysql-5.0']
 | 
					          directories: ['../mysql-5.0']
 | 
				
			||||||
      env: ['MATRIX_EVAL="CC=clang-3.6 && CXX=clang++-3.6"']
 | 
					      env:
 | 
				
			||||||
 | 
					        - MATRIX_EVAL="CC=clang-3.8 && CXX=clang++-3.8"
 | 
				
			||||||
 | 
					        - SDKS=episode1,css,tf2,l4d2,csgo,dota
 | 
				
			||||||
 | 
					        - MODE=optimize
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    - os: linux
 | 
					    - os: linux
 | 
				
			||||||
 | 
					      dist: trusty
 | 
				
			||||||
      sudo: false
 | 
					      sudo: false
 | 
				
			||||||
      language: cpp
 | 
					      language: cpp
 | 
				
			||||||
      addons:
 | 
					      addons:
 | 
				
			||||||
        apt:
 | 
					        apt:
 | 
				
			||||||
          packages: ['clang-3.8', 'lib32stdc++6', 'lib32z1-dev', 'libc6-dev-i386', 'linux-libc-dev', 'g++-multilib']
 | 
					          sources:
 | 
				
			||||||
 | 
					            - ubuntu-toolchain-r-test
 | 
				
			||||||
 | 
					          packages: ['clang-3.4', 'lib32stdc++6', 'lib32z1-dev', 'libc6-dev-i386', 'linux-libc-dev:i386', 'g++-4.9-multilib']
 | 
				
			||||||
        cache:
 | 
					        cache:
 | 
				
			||||||
          directories: ['../mysql-5.0']
 | 
					          directories: ['../mysql-5.0']
 | 
				
			||||||
      env: ['MATRIX_EVAL="CC=clang-3.8 && CXX=clang++-3.8"']
 | 
					      env:
 | 
				
			||||||
 | 
					        - MATRIX_EVAL="CC=clang && CXX=clang++"
 | 
				
			||||||
 | 
					        - SDKS=episode1,css,tf2,l4d2,csgo,dota
 | 
				
			||||||
 | 
					        - MODE=optimize
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    - os: osx
 | 
				
			||||||
 | 
					      osx_image: xcode7.2
 | 
				
			||||||
 | 
					      language: cpp
 | 
				
			||||||
 | 
					      env:
 | 
				
			||||||
 | 
					        - MATRIX_EVAL="CC=clang && CXX=clang++"
 | 
				
			||||||
 | 
					        - SDKS=episode1,css,tf2,l4d2,csgo,dota
 | 
				
			||||||
 | 
					        - MODE=optimize
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # # This is a faster test for the latest g++.
 | 
				
			||||||
 | 
					    # - os: linux
 | 
				
			||||||
 | 
					    #   dist: bionic
 | 
				
			||||||
 | 
					    #   sudo: false
 | 
				
			||||||
 | 
					    #   language: cpp
 | 
				
			||||||
 | 
					    #   addons:
 | 
				
			||||||
 | 
					    #     apt:
 | 
				
			||||||
 | 
					    #       packages: ['lib32stdc++6', 'lib32z1-dev', 'libc6-dev-i386', 'linux-libc-dev:i386', 'g++-multilib', 'g++']
 | 
				
			||||||
 | 
					    #     cache:
 | 
				
			||||||
 | 
					    #       directories: ['../mysql-5.0']
 | 
				
			||||||
 | 
					    #   env:
 | 
				
			||||||
 | 
					    #     - MATRIX_EVAL="CC=gcc && CXX=g++"
 | 
				
			||||||
 | 
					    #     - SDKS=csgo
 | 
				
			||||||
 | 
					    #     # GCC currently fails in opt builds trying to inline stuff in sqlite3.c.
 | 
				
			||||||
 | 
					    #     - MODE=debug
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # This is a faster test for the latest clang.
 | 
				
			||||||
    - os: linux
 | 
					    - os: linux
 | 
				
			||||||
 | 
					      dist: bionic
 | 
				
			||||||
      sudo: false
 | 
					      sudo: false
 | 
				
			||||||
      language: cpp
 | 
					      language: cpp
 | 
				
			||||||
      addons:
 | 
					      addons:
 | 
				
			||||||
        apt:
 | 
					        apt:
 | 
				
			||||||
          sources: ['llvm-toolchain-trusty-4.0']
 | 
					          packages: ['lib32stdc++6', 'lib32z1-dev', 'libc6-dev-i386', 'linux-libc-dev:i386', 'g++-multilib', 'clang']
 | 
				
			||||||
          packages: ['clang-4.0', 'lib32stdc++6', 'lib32z1-dev', 'libc6-dev-i386', 'linux-libc-dev', 'g++-multilib']
 | 
					 | 
				
			||||||
        cache:
 | 
					        cache:
 | 
				
			||||||
          directories: ['../mysql-5.0']
 | 
					          directories: ['../mysql-5.0']
 | 
				
			||||||
      env: ['MATRIX_EVAL="CC=clang-4.0 && CXX=clang++-4.0"']
 | 
					      env:
 | 
				
			||||||
 | 
					        - MATRIX_EVAL="CC=clang && CXX=clang++"
 | 
				
			||||||
    - os: linux
 | 
					        - SDKS=csgo
 | 
				
			||||||
      sudo: false
 | 
					        - MODE=optimize
 | 
				
			||||||
      language: cpp
 | 
					 | 
				
			||||||
      addons:
 | 
					 | 
				
			||||||
        apt:
 | 
					 | 
				
			||||||
          sources: ['llvm-toolchain-trusty-5.0']
 | 
					 | 
				
			||||||
          packages: ['clang-5.0', 'lib32stdc++6', 'lib32z1-dev', 'libc6-dev-i386', 'linux-libc-dev', 'g++-multilib']
 | 
					 | 
				
			||||||
        cache:
 | 
					 | 
				
			||||||
          directories: ['../mysql-5.0']
 | 
					 | 
				
			||||||
      env: ['MATRIX_EVAL="CC=clang-5.0 && CXX=clang++-5.0"']
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    - os: linux
 | 
					 | 
				
			||||||
      sudo: false
 | 
					 | 
				
			||||||
      language: cpp
 | 
					 | 
				
			||||||
      addons:
 | 
					 | 
				
			||||||
        apt:
 | 
					 | 
				
			||||||
          sources: ['ubuntu-toolchain-r-test']
 | 
					 | 
				
			||||||
          packages: ['g++-6', 'g++-6-multilib', 'lib32stdc++6', 'lib32z1-dev', 'libc6-dev-i386', 'linux-libc-dev', 'g++-multilib']
 | 
					 | 
				
			||||||
        cache:
 | 
					 | 
				
			||||||
          directories: ['../mysql-5.0']
 | 
					 | 
				
			||||||
      env: ['MATRIX_EVAL="CC=gcc-6 && CXX=g++-6"']
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  allow_failures:
 | 
					 | 
				
			||||||
    - env: MATRIX_EVAL="CC=clang-3.7 && CXX=clang++-3.7"
 | 
					 | 
				
			||||||
    - env: MATRIX_EVAL="CC=clang-3.9 && CXX=clang++-3.9"
 | 
					 | 
				
			||||||
    - env: MATRIX_EVAL="CC=gcc-4.8 && CXX=g++-4.8"
 | 
					 | 
				
			||||||
    - env: MATRIX_EVAL="CC=gcc-4.9 && CXX=g++-4.9"
 | 
					 | 
				
			||||||
    - env: MATRIX_EVAL="CC=gcc-5 && CXX=g++-5"
 | 
					 | 
				
			||||||
    - env: MATRIX_EVAL="CC=gcc-7 && CXX=g++-7"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
before_script:
 | 
					before_script:
 | 
				
			||||||
  - CHECKOUT_DIR=$PWD && cd .. && $CHECKOUT_DIR/tools/checkout-deps.sh && cd $CHECKOUT_DIR
 | 
					  - CHECKOUT_DIR=$PWD && cd .. && $CHECKOUT_DIR/tools/checkout-deps.sh && cd $CHECKOUT_DIR
 | 
				
			||||||
@ -114,5 +84,7 @@ script:
 | 
				
			|||||||
  - mkdir build && cd build
 | 
					  - mkdir build && cd build
 | 
				
			||||||
  - PATH="~/.local/bin:$PATH"
 | 
					  - PATH="~/.local/bin:$PATH"
 | 
				
			||||||
  - eval "${MATRIX_EVAL}"
 | 
					  - eval "${MATRIX_EVAL}"
 | 
				
			||||||
  - python ../configure.py --enable-optimize --sdks=episode1,css,tf2,l4d2,csgo,dota
 | 
					  - eval "${CC} --version"
 | 
				
			||||||
 | 
					  - eval "${CXX} --version"
 | 
				
			||||||
 | 
					  - python ../configure.py --enable-${MODE} --sdks=${SDKS}
 | 
				
			||||||
  - ambuild
 | 
					  - ambuild
 | 
				
			||||||
 | 
				
			|||||||
@ -281,8 +281,13 @@ class SMConfig(object):
 | 
				
			|||||||
      '-msse',
 | 
					      '-msse',
 | 
				
			||||||
      '-fvisibility=hidden',
 | 
					      '-fvisibility=hidden',
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if cxx.version == 'apple-clang-6.0' or cxx.version == 'clang-3.4':
 | 
				
			||||||
 | 
					      cxx.cxxflags += ['-std=c++1y']
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					      cxx.cxxflags += ['-std=c++14']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    cxx.cxxflags += [
 | 
					    cxx.cxxflags += [
 | 
				
			||||||
      '-std=c++11',
 | 
					 | 
				
			||||||
      '-fno-exceptions',
 | 
					      '-fno-exceptions',
 | 
				
			||||||
      '-fno-threadsafe-statics',
 | 
					      '-fno-threadsafe-statics',
 | 
				
			||||||
      '-Wno-non-virtual-dtor',
 | 
					      '-Wno-non-virtual-dtor',
 | 
				
			||||||
@ -292,11 +297,11 @@ class SMConfig(object):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    have_gcc = cxx.family == 'gcc'
 | 
					    have_gcc = cxx.family == 'gcc'
 | 
				
			||||||
    have_clang = cxx.family == 'clang'
 | 
					    have_clang = cxx.family == 'clang'
 | 
				
			||||||
    if cxx.version >= 'clang-3.9':
 | 
					    if cxx.version >= 'clang-3.9' or cxx.version == 'clang-3.4' or cxx.version > 'apple-clang-6.0':
 | 
				
			||||||
      cxx.cxxflags += ['-Wno-expansion-to-defined']
 | 
					      cxx.cxxflags += ['-Wno-expansion-to-defined']
 | 
				
			||||||
    if cxx.version == 'clang-3.9' or cxx.version == 'apple-clang-8.0':
 | 
					    if cxx.version == 'clang-3.9' or cxx.version == 'apple-clang-8.0':
 | 
				
			||||||
      cxx.cflags += ['-Wno-varargs']
 | 
					      cxx.cflags += ['-Wno-varargs']
 | 
				
			||||||
    if cxx.version >= 'clang-3.6' or cxx.version >= 'apple-clang-7.0':
 | 
					    if cxx.version >= 'clang-3.4' or cxx.version >= 'apple-clang-7.0':
 | 
				
			||||||
      cxx.cxxflags += ['-Wno-inconsistent-missing-override']
 | 
					      cxx.cxxflags += ['-Wno-inconsistent-missing-override']
 | 
				
			||||||
    if cxx.version >= 'clang-2.9' or cxx.version >= 'apple-clang-3.0':
 | 
					    if cxx.version >= 'clang-2.9' or cxx.version >= 'apple-clang-3.0':
 | 
				
			||||||
      cxx.cxxflags += ['-Wno-null-dereference']
 | 
					      cxx.cxxflags += ['-Wno-null-dereference']
 | 
				
			||||||
@ -316,6 +321,13 @@ class SMConfig(object):
 | 
				
			|||||||
        cxx.cxxflags += ['-Wno-deprecated']
 | 
					        cxx.cxxflags += ['-Wno-deprecated']
 | 
				
			||||||
      cxx.cflags += ['-Wno-sometimes-uninitialized']
 | 
					      cxx.cflags += ['-Wno-sometimes-uninitialized']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Work around SDK warnings.
 | 
				
			||||||
 | 
					    if cxx.version >= 'clang-10.0':
 | 
				
			||||||
 | 
					        cxx.cflags += [
 | 
				
			||||||
 | 
					            '-Wno-implicit-int-float-conversion',
 | 
				
			||||||
 | 
					            '-Wno-tautological-overlap-compare',
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if have_gcc:
 | 
					    if have_gcc:
 | 
				
			||||||
      cxx.cflags += ['-mfpmath=sse']
 | 
					      cxx.cflags += ['-mfpmath=sse']
 | 
				
			||||||
      cxx.cflags += ['-Wno-maybe-uninitialized']
 | 
					      cxx.cflags += ['-Wno-maybe-uninitialized']
 | 
				
			||||||
@ -379,16 +391,16 @@ class SMConfig(object):
 | 
				
			|||||||
      cxx.linkflags += ['-static-libgcc']
 | 
					      cxx.linkflags += ['-static-libgcc']
 | 
				
			||||||
    elif cxx.family == 'clang':
 | 
					    elif cxx.family == 'clang':
 | 
				
			||||||
      cxx.linkflags += ['-lgcc_eh']
 | 
					      cxx.linkflags += ['-lgcc_eh']
 | 
				
			||||||
 | 
					    cxx.linkflags += ['-static-libstdc++']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def configure_mac(self, cxx):
 | 
					  def configure_mac(self, cxx):
 | 
				
			||||||
    cxx.defines += ['OSX', '_OSX', 'POSIX', 'KE_ABSOLUTELY_NO_STL']
 | 
					    cxx.defines += ['OSX', '_OSX', 'POSIX', 'KE_ABSOLUTELY_NO_STL']
 | 
				
			||||||
    cxx.cflags += ['-mmacosx-version-min=10.5']
 | 
					    cxx.cflags += ['-mmacosx-version-min=10.7']
 | 
				
			||||||
    cxx.linkflags += [
 | 
					    cxx.linkflags += [
 | 
				
			||||||
      '-mmacosx-version-min=10.5',
 | 
					      '-mmacosx-version-min=10.7',
 | 
				
			||||||
      '-lstdc++',
 | 
					      '-stdlib=libc++',
 | 
				
			||||||
      '-stdlib=libstdc++',
 | 
					 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
    cxx.cxxflags += ['-stdlib=libstdc++']
 | 
					    cxx.cxxflags += ['-stdlib=libc++']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def configure_windows(self, cxx):
 | 
					  def configure_windows(self, cxx):
 | 
				
			||||||
    cxx.defines += ['WIN32', '_WINDOWS']
 | 
					    cxx.defines += ['WIN32', '_WINDOWS']
 | 
				
			||||||
@ -538,7 +550,9 @@ class SMConfig(object):
 | 
				
			|||||||
      if builder.target.platform in ['linux', 'mac']:
 | 
					      if builder.target.platform in ['linux', 'mac']:
 | 
				
			||||||
        compiler.defines += ['NO_HOOK_MALLOC', 'NO_MALLOC_OVERRIDE']
 | 
					        compiler.defines += ['NO_HOOK_MALLOC', 'NO_MALLOC_OVERRIDE']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if sdk.name in ['csgo', 'blade'] and builder.target.platform == 'linux':
 | 
					    if builder.target.platform == 'linux':
 | 
				
			||||||
 | 
					        if sdk.name in ['csgo', 'blade']:
 | 
				
			||||||
 | 
					          compiler.linkflags.remove('-static-libstdc++')
 | 
				
			||||||
          compiler.linkflags += ['-lstdc++']
 | 
					          compiler.linkflags += ['-lstdc++']
 | 
				
			||||||
          compiler.defines += ['_GLIBCXX_USE_CXX11_ABI=0']
 | 
					          compiler.defines += ['_GLIBCXX_USE_CXX11_ABI=0']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -35,8 +35,7 @@ for arch in SM.archs:
 | 
				
			|||||||
    'smn_maplists.cpp',
 | 
					    'smn_maplists.cpp',
 | 
				
			||||||
    'ADTFactory.cpp',
 | 
					    'ADTFactory.cpp',
 | 
				
			||||||
    'smn_adt_stack.cpp',
 | 
					    'smn_adt_stack.cpp',
 | 
				
			||||||
    'thread/ThreadWorker.cpp',
 | 
					    'BaseWorker.cpp',
 | 
				
			||||||
    'thread/BaseWorker.cpp',
 | 
					 | 
				
			||||||
    'ThreadSupport.cpp',
 | 
					    'ThreadSupport.cpp',
 | 
				
			||||||
    'smn_float.cpp',
 | 
					    'smn_float.cpp',
 | 
				
			||||||
    'TextParsers.cpp',
 | 
					    'TextParsers.cpp',
 | 
				
			||||||
@ -90,9 +89,4 @@ for arch in SM.archs:
 | 
				
			|||||||
  if arch == 'x64':
 | 
					  if arch == 'x64':
 | 
				
			||||||
    binary.sources += ['PseudoAddrManager.cpp']
 | 
					    binary.sources += ['PseudoAddrManager.cpp']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if builder.target.platform == 'windows':
 | 
					 | 
				
			||||||
    binary.sources += ['thread/WinThreads.cpp']
 | 
					 | 
				
			||||||
  else:
 | 
					 | 
				
			||||||
    binary.sources += ['thread/PosixThreads.cpp']
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  SM.binaries += [builder.Add(binary)]
 | 
					  SM.binaries += [builder.Add(binary)]
 | 
				
			||||||
 | 
				
			|||||||
@ -43,6 +43,7 @@ class BaseWorker;
 | 
				
			|||||||
class SWThreadHandle : public IThreadHandle
 | 
					class SWThreadHandle : public IThreadHandle
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	friend class BaseWorker;
 | 
						friend class BaseWorker;
 | 
				
			||||||
 | 
						friend class CompatWorker;
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
	SWThreadHandle(IThreadCreator *parent, const ThreadParams *p, IThread *thread);
 | 
						SWThreadHandle(IThreadCreator *parent, const ThreadParams *p, IThread *thread);
 | 
				
			||||||
	IThread *GetThread();
 | 
						IThread *GetThread();
 | 
				
			||||||
@ -1,5 +1,5 @@
 | 
				
			|||||||
/**
 | 
					/**
 | 
				
			||||||
 * vim: set ts=4 sw=4 :
 | 
					 * vim: set ts=4 sw=4 tw=99 noet :
 | 
				
			||||||
 * =============================================================================
 | 
					 * =============================================================================
 | 
				
			||||||
 * SourceMod
 | 
					 * SourceMod
 | 
				
			||||||
 * Copyright (C) 2004-2009 AlliedModders LLC.  All rights reserved.
 | 
					 * Copyright (C) 2004-2009 AlliedModders LLC.  All rights reserved.
 | 
				
			||||||
@ -29,17 +29,515 @@
 | 
				
			|||||||
 * Version: $Id$
 | 
					 * Version: $Id$
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
#include <sm_platform.h>
 | 
					#include <sm_platform.h>
 | 
				
			||||||
 | 
					#include <amtl/am-deque.h>
 | 
				
			||||||
 | 
					#include <amtl/am-maybe.h>
 | 
				
			||||||
 | 
					#include <atomic>
 | 
				
			||||||
 | 
					#include <chrono>
 | 
				
			||||||
 | 
					#include <condition_variable>
 | 
				
			||||||
 | 
					#include <memory>
 | 
				
			||||||
 | 
					#include <mutex>
 | 
				
			||||||
 | 
					#include <thread>
 | 
				
			||||||
 | 
					#include "BaseWorker.h"
 | 
				
			||||||
#include "ThreadSupport.h"
 | 
					#include "ThreadSupport.h"
 | 
				
			||||||
#include "common_logic.h"
 | 
					#include "common_logic.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if defined PLATFORM_POSIX
 | 
					static constexpr unsigned int DEFAULT_THINK_TIME_MS	= 20;
 | 
				
			||||||
#include "thread/PosixThreads.h"
 | 
					 | 
				
			||||||
#elif defined PLATFORM_WINDOWS
 | 
					 | 
				
			||||||
#include "thread/WinThreads.h"
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
MainThreader g_MainThreader;
 | 
					class CompatWorker final : public IThreadWorker
 | 
				
			||||||
IThreader *g_pThreader = &g_MainThreader;
 | 
					{
 | 
				
			||||||
 | 
					  public:
 | 
				
			||||||
 | 
						explicit CompatWorker(IThreadWorkerCallbacks* callbacks);
 | 
				
			||||||
 | 
						~CompatWorker();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void MakeThread(IThread *pThread) override;
 | 
				
			||||||
 | 
						IThreadHandle *MakeThread(IThread *pThread, ThreadFlags flags) override;
 | 
				
			||||||
 | 
						IThreadHandle *MakeThread(IThread *pThread, const ThreadParams *params) override;
 | 
				
			||||||
 | 
						void GetPriorityBounds(ThreadPriority &max, ThreadPriority &min) override;
 | 
				
			||||||
 | 
						unsigned int RunFrame() override;
 | 
				
			||||||
 | 
						bool Pause() override;
 | 
				
			||||||
 | 
						bool Unpause() override;
 | 
				
			||||||
 | 
						bool Start() override;
 | 
				
			||||||
 | 
						bool Stop(bool flush) override;
 | 
				
			||||||
 | 
						WorkerState GetStatus(unsigned int *numThreads) override;
 | 
				
			||||||
 | 
						void SetMaxThreadsPerFrame(unsigned int threads) override;
 | 
				
			||||||
 | 
						void SetThinkTimePerFrame(unsigned int thinktime) override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  private:
 | 
				
			||||||
 | 
						void Flush();
 | 
				
			||||||
 | 
						void Worker();
 | 
				
			||||||
 | 
						void RunWork(SWThreadHandle* handle);
 | 
				
			||||||
 | 
						void RunWorkLocked(std::unique_lock<std::mutex>* lock, SWThreadHandle* handle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  private:
 | 
				
			||||||
 | 
						IThreadWorkerCallbacks* callbacks_;
 | 
				
			||||||
 | 
						WorkerState state_;
 | 
				
			||||||
 | 
						std::mutex mutex_;
 | 
				
			||||||
 | 
						std::condition_variable work_cv_;
 | 
				
			||||||
 | 
						ke::Deque<SWThreadHandle*> work_;
 | 
				
			||||||
 | 
						std::unique_ptr<std::thread> thread_;
 | 
				
			||||||
 | 
						std::atomic<unsigned int> jobs_per_wakeup_;
 | 
				
			||||||
 | 
						std::atomic<unsigned int> wait_between_jobs_;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CompatWorker::CompatWorker(IThreadWorkerCallbacks* callbacks)
 | 
				
			||||||
 | 
						: callbacks_(callbacks),
 | 
				
			||||||
 | 
						  state_(Worker_Stopped),
 | 
				
			||||||
 | 
						  jobs_per_wakeup_(SM_DEFAULT_THREADS_PER_FRAME),
 | 
				
			||||||
 | 
						  wait_between_jobs_(DEFAULT_THINK_TIME_MS)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CompatWorker::~CompatWorker()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						Stop(false /* ignored */);
 | 
				
			||||||
 | 
						Flush();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool CompatWorker::Start()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						std::lock_guard<std::mutex> lock(mutex_);
 | 
				
			||||||
 | 
						if (state_ != Worker_Stopped)
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						thread_ = std::make_unique<std::thread>([this]() -> void {
 | 
				
			||||||
 | 
							Worker();
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
						state_ = Worker_Running;
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool CompatWorker::Stop(bool)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							std::lock_guard<std::mutex> lock(mutex_);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (state_ <= Worker_Stopped)
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							state_ = Worker_Stopped;
 | 
				
			||||||
 | 
							work_cv_.notify_all();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						thread_->join();
 | 
				
			||||||
 | 
						thread_ = nullptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Flush();
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool CompatWorker::Pause()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						std::lock_guard<std::mutex> lock(mutex_);
 | 
				
			||||||
 | 
						if (state_ != Worker_Running)
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						state_ = Worker_Paused;
 | 
				
			||||||
 | 
						work_cv_.notify_all();
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool CompatWorker::Unpause()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						std::lock_guard<std::mutex> lock(mutex_);
 | 
				
			||||||
 | 
						if (state_ != Worker_Paused)
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						state_ = Worker_Running;
 | 
				
			||||||
 | 
						work_cv_.notify_all();
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void CompatWorker::Flush()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						while (!work_.empty()) {
 | 
				
			||||||
 | 
							auto handle = work_.popFrontCopy();
 | 
				
			||||||
 | 
							handle->GetThread()->OnTerminate(handle, true);
 | 
				
			||||||
 | 
							if (handle->m_params.flags & Thread_AutoRelease)
 | 
				
			||||||
 | 
								delete handle;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void CompatWorker::Worker()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						// Note: this must be first to ensure an ordering between Worker() and
 | 
				
			||||||
 | 
						// Start(). It must also be outside of the loop to ensure the lock is
 | 
				
			||||||
 | 
						// held across wakeup and retesting the predicates.
 | 
				
			||||||
 | 
						std::unique_lock<std::mutex> lock(mutex_);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (callbacks_) {
 | 
				
			||||||
 | 
							lock.unlock();
 | 
				
			||||||
 | 
							callbacks_->OnWorkerStart(this);
 | 
				
			||||||
 | 
							lock.lock();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						typedef std::chrono::system_clock Clock;
 | 
				
			||||||
 | 
						typedef std::chrono::time_point<Clock> TimePoint;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						auto can_work = [this]() -> bool {
 | 
				
			||||||
 | 
							return state_ == Worker_Running && !work_.empty();
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ke::Maybe<TimePoint> wait;
 | 
				
			||||||
 | 
						unsigned int work_in_frame = 0;
 | 
				
			||||||
 | 
						for (;;) {
 | 
				
			||||||
 | 
							if (state_ == Worker_Stopped)
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (!can_work()) {
 | 
				
			||||||
 | 
								// Wait for work or a Stop.
 | 
				
			||||||
 | 
								work_cv_.wait(lock);
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (wait.isValid()) {
 | 
				
			||||||
 | 
								// Wait until the specified time has passed. If we wake up with a
 | 
				
			||||||
 | 
								// timeout, then the wait has elapsed, so reset the holder.
 | 
				
			||||||
 | 
								if (work_cv_.wait_until(lock, wait.get()) == std::cv_status::timeout)
 | 
				
			||||||
 | 
									wait = ke::Nothing();
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							assert(state_ == Worker_Running);
 | 
				
			||||||
 | 
							assert(!work_.empty());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							SWThreadHandle* handle = work_.popFrontCopy();
 | 
				
			||||||
 | 
							RunWorkLocked(&lock, handle);
 | 
				
			||||||
 | 
							work_in_frame++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// If we've reached our max jobs per "frame", signal that the next
 | 
				
			||||||
 | 
							// immediate job must be delayed. We retain the old ThreadWorker
 | 
				
			||||||
 | 
							// behavior by checking if the queue has more work. Thus, a delay
 | 
				
			||||||
 | 
							// only occurs if two jobs would be processed in the same wakeup.
 | 
				
			||||||
 | 
							if (work_in_frame >= jobs_per_wakeup_ && wait_between_jobs_ && can_work())
 | 
				
			||||||
 | 
								wait = ke::Some(Clock::now() + std::chrono::milliseconds(wait_between_jobs_));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						assert(lock.owns_lock());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while (!work_.empty()) {
 | 
				
			||||||
 | 
							SWThreadHandle* handle = work_.popFrontCopy();
 | 
				
			||||||
 | 
							RunWorkLocked(&lock, handle);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					unsigned int CompatWorker::RunFrame()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned int nprocessed = 0;
 | 
				
			||||||
 | 
						for (unsigned int i = 1; i <= jobs_per_wakeup_; i++) {
 | 
				
			||||||
 | 
							SWThreadHandle* handle;
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								std::lock_guard<std::mutex> lock(mutex_);
 | 
				
			||||||
 | 
								if (work_.empty())
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								handle = work_.popFrontCopy();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							RunWork(handle);
 | 
				
			||||||
 | 
							nprocessed++;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nprocessed;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void CompatWorker::RunWorkLocked(std::unique_lock<std::mutex>* lock, SWThreadHandle* handle)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						lock->unlock();
 | 
				
			||||||
 | 
						RunWork(handle);
 | 
				
			||||||
 | 
						lock->lock();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void CompatWorker::RunWork(SWThreadHandle* handle)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						bool autorelease = !!(handle->m_params.flags & Thread_AutoRelease);
 | 
				
			||||||
 | 
						handle->m_state = Thread_Running;
 | 
				
			||||||
 | 
						handle->GetThread()->RunThread(handle);
 | 
				
			||||||
 | 
						handle->m_state = Thread_Done;
 | 
				
			||||||
 | 
						handle->GetThread()->OnTerminate(handle, false);
 | 
				
			||||||
 | 
						if (autorelease)
 | 
				
			||||||
 | 
							delete handle;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void CompatWorker::MakeThread(IThread *pThread)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						ThreadParams params;
 | 
				
			||||||
 | 
						params.flags = Thread_AutoRelease;
 | 
				
			||||||
 | 
						MakeThread(pThread, ¶ms);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					IThreadHandle *CompatWorker::MakeThread(IThread *pThread, ThreadFlags flags)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						ThreadParams params;
 | 
				
			||||||
 | 
						params.flags = flags;
 | 
				
			||||||
 | 
						return MakeThread(pThread, ¶ms);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					IThreadHandle *CompatWorker::MakeThread(IThread *pThread, const ThreadParams *params)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						std::lock_guard<std::mutex> lock(mutex_);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ThreadParams def_params;
 | 
				
			||||||
 | 
						if (!params)
 | 
				
			||||||
 | 
							params = &def_params;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (state_ <= Worker_Stopped)
 | 
				
			||||||
 | 
							return nullptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						SWThreadHandle* handle = new SWThreadHandle(this, params, pThread);
 | 
				
			||||||
 | 
						work_.append(handle);
 | 
				
			||||||
 | 
						work_cv_.notify_one();
 | 
				
			||||||
 | 
						return handle;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void CompatWorker::GetPriorityBounds(ThreadPriority &max, ThreadPriority &min)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						min = ThreadPrio_Normal;
 | 
				
			||||||
 | 
						max = ThreadPrio_Normal;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void CompatWorker::SetMaxThreadsPerFrame(unsigned int threads)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						jobs_per_wakeup_ = threads;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void CompatWorker::SetThinkTimePerFrame(unsigned int thinktime)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						wait_between_jobs_ = thinktime;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					WorkerState CompatWorker::GetStatus(unsigned int *numThreads)
 | 
				
			||||||
 | 
					{ 
 | 
				
			||||||
 | 
						std::lock_guard<std::mutex> lock(mutex_);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// This number is meaningless and the status is racy.
 | 
				
			||||||
 | 
						if (numThreads)
 | 
				
			||||||
 | 
							*numThreads = jobs_per_wakeup_;
 | 
				
			||||||
 | 
						return state_;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class CompatThread final : public IThreadHandle
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
						CompatThread(IThread* callbacks, const ThreadParams* params);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool WaitForThread() override;
 | 
				
			||||||
 | 
						void DestroyThis() override;
 | 
				
			||||||
 | 
						IThreadCreator *Parent() override;
 | 
				
			||||||
 | 
						void GetParams(ThreadParams *ptparams) override;
 | 
				
			||||||
 | 
						ThreadPriority GetPriority() override;
 | 
				
			||||||
 | 
						bool SetPriority(ThreadPriority prio) override;
 | 
				
			||||||
 | 
						ThreadState GetState() override;
 | 
				
			||||||
 | 
						bool Unpause() override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
						void Run();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
						IThread* callbacks_;
 | 
				
			||||||
 | 
						ThreadParams params_;
 | 
				
			||||||
 | 
						std::unique_ptr<std::thread> thread_;
 | 
				
			||||||
 | 
						std::mutex mutex_;
 | 
				
			||||||
 | 
						std::condition_variable check_cv_;
 | 
				
			||||||
 | 
						std::atomic<bool> finished_;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CompatThread::CompatThread(IThread* callbacks, const ThreadParams* params)
 | 
				
			||||||
 | 
						: callbacks_(callbacks),
 | 
				
			||||||
 | 
						  params_(*params)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (!(params_.flags & Thread_CreateSuspended))
 | 
				
			||||||
 | 
							Unpause();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool CompatThread::Unpause()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						std::unique_lock<std::mutex> lock(mutex_);
 | 
				
			||||||
 | 
						if (thread_)
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						thread_ = std::make_unique<std::thread>([this]() -> void {
 | 
				
			||||||
 | 
							Run();
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void CompatThread::Run()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						// Create an ordering between when the thread runs and when thread_ is assigned.
 | 
				
			||||||
 | 
						std::unique_lock<std::mutex> lock(mutex_);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						lock.unlock();
 | 
				
			||||||
 | 
						callbacks_->RunThread(this);
 | 
				
			||||||
 | 
						finished_ = true;
 | 
				
			||||||
 | 
						callbacks_->OnTerminate(this, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (params_.flags & Thread_AutoRelease) {
 | 
				
			||||||
 | 
							// There should be no handles outstanding, so it's safe to self-destruct.
 | 
				
			||||||
 | 
							thread_->detach();
 | 
				
			||||||
 | 
							delete this;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						lock.lock();
 | 
				
			||||||
 | 
						callbacks_ = nullptr;
 | 
				
			||||||
 | 
						check_cv_.notify_all();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool CompatThread::WaitForThread()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						std::unique_lock<std::mutex> lock(mutex_);
 | 
				
			||||||
 | 
						for (;;) {
 | 
				
			||||||
 | 
							// When done, callbacks are unset. If paused, this will deadlock.
 | 
				
			||||||
 | 
							if (!callbacks_)
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							check_cv_.wait(lock);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						thread_->join();
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ThreadState CompatThread::GetState()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						std::unique_lock<std::mutex> lock(mutex_);
 | 
				
			||||||
 | 
						if (!thread_)
 | 
				
			||||||
 | 
							return Thread_Paused;
 | 
				
			||||||
 | 
						return finished_ ? Thread_Done : Thread_Running;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void CompatThread::DestroyThis()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						delete this;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ThreadPriority CompatThread::GetPriority()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return ThreadPrio_Normal;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool CompatThread::SetPriority(ThreadPriority prio)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return prio == ThreadPrio_Normal;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					IThreadCreator *CompatThread::Parent()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return g_pThreader;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void CompatThread::GetParams(ThreadParams *ptparams)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						*ptparams = params_;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class CompatMutex : public IMutex
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
						bool TryLock() {
 | 
				
			||||||
 | 
							return mutex_.try_lock();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						void Lock() {
 | 
				
			||||||
 | 
							mutex_.lock();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						void Unlock() {
 | 
				
			||||||
 | 
							mutex_.unlock();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						void DestroyThis() {
 | 
				
			||||||
 | 
							delete this;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
						std::mutex mutex_;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class CompatThreader final : public IThreader
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
						void MakeThread(IThread *pThread) override;
 | 
				
			||||||
 | 
						IThreadHandle *MakeThread(IThread *pThread, ThreadFlags flags) override;
 | 
				
			||||||
 | 
						IThreadHandle *MakeThread(IThread *pThread, const ThreadParams *params) override;
 | 
				
			||||||
 | 
						void GetPriorityBounds(ThreadPriority &max, ThreadPriority &min) override;
 | 
				
			||||||
 | 
						IMutex *MakeMutex() override;
 | 
				
			||||||
 | 
						void ThreadSleep(unsigned int ms) override;
 | 
				
			||||||
 | 
						IEventSignal *MakeEventSignal() override;
 | 
				
			||||||
 | 
						IThreadWorker *MakeWorker(IThreadWorkerCallbacks *hooks, bool threaded) override;
 | 
				
			||||||
 | 
						void DestroyWorker(IThreadWorker *pWorker) override;
 | 
				
			||||||
 | 
					} sCompatThreader;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void CompatThreader::MakeThread(IThread *pThread)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						ThreadParams params;
 | 
				
			||||||
 | 
						params.flags = Thread_AutoRelease;
 | 
				
			||||||
 | 
						MakeThread(pThread, ¶ms);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					IThreadHandle *CompatThreader::MakeThread(IThread *pThread, ThreadFlags flags)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						ThreadParams params;
 | 
				
			||||||
 | 
						params.flags = flags;
 | 
				
			||||||
 | 
						return MakeThread(pThread, ¶ms);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					IThreadHandle *CompatThreader::MakeThread(IThread *pThread, const ThreadParams *params)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						ThreadParams def_params;
 | 
				
			||||||
 | 
						if (!params)
 | 
				
			||||||
 | 
							params = &def_params;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return new CompatThread(pThread, params);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void CompatThreader::GetPriorityBounds(ThreadPriority &max, ThreadPriority &min)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						min = ThreadPrio_Normal;
 | 
				
			||||||
 | 
						max = ThreadPrio_Normal;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					IMutex *CompatThreader::MakeMutex()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return new CompatMutex();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void CompatThreader::ThreadSleep(unsigned int ms)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						std::this_thread::sleep_for(std::chrono::milliseconds(ms));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class CompatEventSignal final : public IEventSignal
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
						void Wait() override {
 | 
				
			||||||
 | 
							std::unique_lock<std::mutex> lock(mutex_);
 | 
				
			||||||
 | 
							cv_.wait(lock);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						void Signal() override {
 | 
				
			||||||
 | 
							std::lock_guard<std::mutex> lock(mutex_);
 | 
				
			||||||
 | 
							cv_.notify_all();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						void DestroyThis() override {
 | 
				
			||||||
 | 
							delete this;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
						std::mutex mutex_;
 | 
				
			||||||
 | 
						std::condition_variable cv_;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					IEventSignal *CompatThreader::MakeEventSignal()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return new CompatEventSignal();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					IThreadWorker *CompatThreader::MakeWorker(IThreadWorkerCallbacks *hooks, bool threaded)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (!threaded)
 | 
				
			||||||
 | 
							return new BaseWorker(hooks);
 | 
				
			||||||
 | 
					    return new CompatWorker(hooks);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void CompatThreader::DestroyWorker(IThreadWorker *pWorker)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						delete pWorker;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					IThreader *g_pThreader = &sCompatThreader;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class RegThreadStuff : public SMGlobalClass
 | 
					class RegThreadStuff : public SMGlobalClass
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
				
			|||||||
@ -32,49 +32,14 @@
 | 
				
			|||||||
#ifndef _INCLUDE_SOURCEMOD_THREAD_SUPPORT_H
 | 
					#ifndef _INCLUDE_SOURCEMOD_THREAD_SUPPORT_H
 | 
				
			||||||
#define _INCLUDE_SOURCEMOD_THREAD_SUPPORT_H
 | 
					#define _INCLUDE_SOURCEMOD_THREAD_SUPPORT_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <mutex>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <IThreader.h>
 | 
					#include <IThreader.h>
 | 
				
			||||||
#include <am-thread-utils.h>
 | 
					#include <am-thread-utils.h>
 | 
				
			||||||
#include <am-utility.h>
 | 
					#include <am-utility.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
using namespace SourceMod;
 | 
					using namespace SourceMod;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class CompatMutex : public IMutex
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
public:
 | 
					 | 
				
			||||||
	bool TryLock() {
 | 
					 | 
				
			||||||
		return mutex_.TryLock();
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	void Lock() {
 | 
					 | 
				
			||||||
		mutex_.Lock();
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	void Unlock() {
 | 
					 | 
				
			||||||
		mutex_.Unlock();
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	void DestroyThis() {
 | 
					 | 
				
			||||||
		delete this;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
private:
 | 
					 | 
				
			||||||
	ke::Mutex mutex_;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class CompatCondVar : public IEventSignal
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
public:
 | 
					 | 
				
			||||||
	void Wait() {
 | 
					 | 
				
			||||||
		ke::AutoLock lock(&cv_);
 | 
					 | 
				
			||||||
		cv_.Wait();
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	void Signal() {
 | 
					 | 
				
			||||||
		ke::AutoLock lock(&cv_);
 | 
					 | 
				
			||||||
		cv_.Notify();
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	void DestroyThis() {
 | 
					 | 
				
			||||||
		delete this;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
private:
 | 
					 | 
				
			||||||
	ke::ConditionVariable cv_;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
extern IThreader *g_pThreader;
 | 
					extern IThreader *g_pThreader;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif //_INCLUDE_SOURCEMOD_THREAD_SUPPORT_H
 | 
					#endif //_INCLUDE_SOURCEMOD_THREAD_SUPPORT_H
 | 
				
			||||||
 | 
				
			|||||||
@ -1,199 +0,0 @@
 | 
				
			|||||||
/**
 | 
					 | 
				
			||||||
 * vim: set ts=4 sw=4 tw=99 noet:
 | 
					 | 
				
			||||||
 * =============================================================================
 | 
					 | 
				
			||||||
 * SourceMod
 | 
					 | 
				
			||||||
 * Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
 | 
					 | 
				
			||||||
 * =============================================================================
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * This program is free software; you can redistribute it and/or modify it under
 | 
					 | 
				
			||||||
 * the terms of the GNU General Public License, version 3.0, as published by the
 | 
					 | 
				
			||||||
 * Free Software Foundation.
 | 
					 | 
				
			||||||
 * 
 | 
					 | 
				
			||||||
 * This program is distributed in the hope that it will be useful, but WITHOUT
 | 
					 | 
				
			||||||
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 | 
					 | 
				
			||||||
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 | 
					 | 
				
			||||||
 * details.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * You should have received a copy of the GNU General Public License along with
 | 
					 | 
				
			||||||
 * this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * As a special exception, AlliedModders LLC gives you permission to link the
 | 
					 | 
				
			||||||
 * code of this program (as well as its derivative works) to "Half-Life 2," the
 | 
					 | 
				
			||||||
 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
 | 
					 | 
				
			||||||
 * by the Valve Corporation.  You must obey the GNU General Public License in
 | 
					 | 
				
			||||||
 * all respects for all other code used.  Additionally, AlliedModders LLC grants
 | 
					 | 
				
			||||||
 * this exception to all derivative works.  AlliedModders LLC defines further
 | 
					 | 
				
			||||||
 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
 | 
					 | 
				
			||||||
 * or <http://www.sourcemod.net/license.php>.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Version: $Id$
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <unistd.h>
 | 
					 | 
				
			||||||
#include "PosixThreads.h"
 | 
					 | 
				
			||||||
#include "ThreadWorker.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
IThreadWorker *PosixThreader::MakeWorker(IThreadWorkerCallbacks *hooks, bool threaded)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if (threaded)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		return new ThreadWorker(hooks, this, DEFAULT_THINK_TIME_MS);
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		return new BaseWorker(hooks);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void PosixThreader::DestroyWorker(IThreadWorker *pWorker)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	delete pWorker;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void PosixThreader::ThreadSleep(unsigned int ms)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	usleep( ms * 1000 );
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void PosixThreader::GetPriorityBounds(ThreadPriority &max, ThreadPriority &min)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	max = ThreadPrio_Normal;
 | 
					 | 
				
			||||||
	min = ThreadPrio_Normal;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
IMutex *PosixThreader::MakeMutex()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return new CompatMutex();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void PosixThreader::MakeThread(IThread *pThread)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	ThreadParams defparams;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	defparams.flags = Thread_AutoRelease;
 | 
					 | 
				
			||||||
	defparams.prio = ThreadPrio_Normal;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	MakeThread(pThread, &defparams);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
IThreadHandle *PosixThreader::MakeThread(IThread *pThread, ThreadFlags flags)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	ThreadParams defparams;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	defparams.flags = flags;
 | 
					 | 
				
			||||||
	defparams.prio = ThreadPrio_Normal;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return MakeThread(pThread, &defparams);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void PosixThreader::ThreadHandle::Run()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	// Wait for an unpause if necessary.
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		ke::AutoLock lock(&m_runlock);
 | 
					 | 
				
			||||||
		if (m_state == Thread_Paused)
 | 
					 | 
				
			||||||
			m_runlock.Wait();
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	m_run->RunThread(this);
 | 
					 | 
				
			||||||
	m_state = Thread_Done;
 | 
					 | 
				
			||||||
	m_run->OnTerminate(this, false);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (m_params.flags & Thread_AutoRelease)
 | 
					 | 
				
			||||||
		delete this;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ThreadParams g_defparams;
 | 
					 | 
				
			||||||
IThreadHandle *PosixThreader::MakeThread(IThread *pThread, const ThreadParams *params)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if (params == NULL)
 | 
					 | 
				
			||||||
		params = &g_defparams;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ThreadHandle* pHandle = new ThreadHandle(this, pThread, params);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	pHandle->m_thread = new ke::Thread([pHandle]() -> void {
 | 
					 | 
				
			||||||
		pHandle->Run();
 | 
					 | 
				
			||||||
	}, "SourceMod");
 | 
					 | 
				
			||||||
	if (!pHandle->m_thread->Succeeded()) {
 | 
					 | 
				
			||||||
		delete pHandle;
 | 
					 | 
				
			||||||
		return NULL;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (!(params->flags & Thread_CreateSuspended))
 | 
					 | 
				
			||||||
		pHandle->Unpause();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return pHandle;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
IEventSignal *PosixThreader::MakeEventSignal()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return new CompatCondVar();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/******************
 | 
					 | 
				
			||||||
* Thread Handles *
 | 
					 | 
				
			||||||
******************/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
PosixThreader::ThreadHandle::ThreadHandle(IThreader *parent, IThread *run, const ThreadParams *params) : 
 | 
					 | 
				
			||||||
	m_parent(parent), m_params(*params), m_run(run), m_state(Thread_Paused)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
PosixThreader::ThreadHandle::~ThreadHandle()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
bool PosixThreader::ThreadHandle::WaitForThread()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if (!m_thread)
 | 
					 | 
				
			||||||
		return false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	m_thread->Join();
 | 
					 | 
				
			||||||
	return true;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ThreadState PosixThreader::ThreadHandle::GetState()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return m_state;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
IThreadCreator *PosixThreader::ThreadHandle::Parent()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return m_parent;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void PosixThreader::ThreadHandle::DestroyThis()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if (m_params.flags & Thread_AutoRelease)
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	delete this;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void PosixThreader::ThreadHandle::GetParams(ThreadParams *ptparams)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if (!ptparams)
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	*ptparams = m_params;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ThreadPriority PosixThreader::ThreadHandle::GetPriority()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return ThreadPrio_Normal;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
bool PosixThreader::ThreadHandle::SetPriority(ThreadPriority prio)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return (prio == ThreadPrio_Normal);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
bool PosixThreader::ThreadHandle::Unpause()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if (m_state != Thread_Paused)
 | 
					 | 
				
			||||||
		return false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ke::AutoLock lock(&m_runlock);
 | 
					 | 
				
			||||||
	m_state = Thread_Running;
 | 
					 | 
				
			||||||
	m_runlock.Notify();
 | 
					 | 
				
			||||||
	return true;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@ -1,86 +0,0 @@
 | 
				
			|||||||
/**
 | 
					 | 
				
			||||||
 * vim: set ts=4 sw=4 tw=99 noet:
 | 
					 | 
				
			||||||
 * =============================================================================
 | 
					 | 
				
			||||||
 * SourceMod
 | 
					 | 
				
			||||||
 * Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
 | 
					 | 
				
			||||||
 * =============================================================================
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * This program is free software; you can redistribute it and/or modify it under
 | 
					 | 
				
			||||||
 * the terms of the GNU General Public License, version 3.0, as published by the
 | 
					 | 
				
			||||||
 * Free Software Foundation.
 | 
					 | 
				
			||||||
 * 
 | 
					 | 
				
			||||||
 * This program is distributed in the hope that it will be useful, but WITHOUT
 | 
					 | 
				
			||||||
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 | 
					 | 
				
			||||||
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 | 
					 | 
				
			||||||
 * details.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * You should have received a copy of the GNU General Public License along with
 | 
					 | 
				
			||||||
 * this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * As a special exception, AlliedModders LLC gives you permission to link the
 | 
					 | 
				
			||||||
 * code of this program (as well as its derivative works) to "Half-Life 2," the
 | 
					 | 
				
			||||||
 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
 | 
					 | 
				
			||||||
 * by the Valve Corporation.  You must obey the GNU General Public License in
 | 
					 | 
				
			||||||
 * all respects for all other code used.  Additionally, AlliedModders LLC grants
 | 
					 | 
				
			||||||
 * this exception to all derivative works.  AlliedModders LLC defines further
 | 
					 | 
				
			||||||
 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
 | 
					 | 
				
			||||||
 * or <http://www.sourcemod.net/license.php>.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Version: $Id$
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifndef _INCLUDE_POSIXTHREADS_H_
 | 
					 | 
				
			||||||
#define _INCLUDE_POSIXTHREADS_H_
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <pthread.h>
 | 
					 | 
				
			||||||
#include <am-thread-utils.h>
 | 
					 | 
				
			||||||
#include "IThreader.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
using namespace SourceMod;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class PosixThreader : public IThreader
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
public:
 | 
					 | 
				
			||||||
	class ThreadHandle : public IThreadHandle
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		friend class PosixThreader;
 | 
					 | 
				
			||||||
	public:
 | 
					 | 
				
			||||||
		ThreadHandle(IThreader *parent, IThread *run, const ThreadParams *params);
 | 
					 | 
				
			||||||
		virtual ~ThreadHandle();
 | 
					 | 
				
			||||||
	public:
 | 
					 | 
				
			||||||
		virtual bool WaitForThread();
 | 
					 | 
				
			||||||
		virtual void DestroyThis();
 | 
					 | 
				
			||||||
		virtual IThreadCreator *Parent();
 | 
					 | 
				
			||||||
		virtual void GetParams(ThreadParams *ptparams);
 | 
					 | 
				
			||||||
		virtual ThreadPriority GetPriority();
 | 
					 | 
				
			||||||
		virtual bool SetPriority(ThreadPriority prio);
 | 
					 | 
				
			||||||
		virtual ThreadState GetState();
 | 
					 | 
				
			||||||
		virtual bool Unpause();
 | 
					 | 
				
			||||||
	public:
 | 
					 | 
				
			||||||
		void Run();
 | 
					 | 
				
			||||||
	protected:
 | 
					 | 
				
			||||||
		IThreader *m_parent;		//Parent handle
 | 
					 | 
				
			||||||
		ThreadParams m_params;		//Current Parameters
 | 
					 | 
				
			||||||
		IThread *m_run;				//Runnable context
 | 
					 | 
				
			||||||
		ke::AutoPtr<ke::Thread> m_thread;
 | 
					 | 
				
			||||||
		ke::ConditionVariable m_runlock;
 | 
					 | 
				
			||||||
		ThreadState m_state;		//internal state
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
public:
 | 
					 | 
				
			||||||
	IMutex *MakeMutex();
 | 
					 | 
				
			||||||
	void MakeThread(IThread *pThread);
 | 
					 | 
				
			||||||
	IThreadHandle *MakeThread(IThread *pThread, ThreadFlags flags);
 | 
					 | 
				
			||||||
	IThreadHandle *MakeThread(IThread *pThread, const ThreadParams *params);
 | 
					 | 
				
			||||||
	void GetPriorityBounds(ThreadPriority &max, ThreadPriority &min);
 | 
					 | 
				
			||||||
	void ThreadSleep(unsigned int ms);
 | 
					 | 
				
			||||||
	IEventSignal *MakeEventSignal();
 | 
					 | 
				
			||||||
	IThreadWorker *MakeWorker(IThreadWorkerCallbacks *hooks, bool threaded);
 | 
					 | 
				
			||||||
	void DestroyWorker(IThreadWorker *pWorker);
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#if defined SM_DEFAULT_THREADER && !defined SM_MAIN_THREADER
 | 
					 | 
				
			||||||
#define SM_MAIN_THREADER PosixThreader;
 | 
					 | 
				
			||||||
typedef class PosixThreader MainThreader;
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif //_INCLUDE_POSIXTHREADS_H_
 | 
					 | 
				
			||||||
@ -1,218 +0,0 @@
 | 
				
			|||||||
/**
 | 
					 | 
				
			||||||
 * vim: set ts=4 :
 | 
					 | 
				
			||||||
 * =============================================================================
 | 
					 | 
				
			||||||
 * SourceMod
 | 
					 | 
				
			||||||
 * Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
 | 
					 | 
				
			||||||
 * =============================================================================
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * This program is free software; you can redistribute it and/or modify it under
 | 
					 | 
				
			||||||
 * the terms of the GNU General Public License, version 3.0, as published by the
 | 
					 | 
				
			||||||
 * Free Software Foundation.
 | 
					 | 
				
			||||||
 * 
 | 
					 | 
				
			||||||
 * This program is distributed in the hope that it will be useful, but WITHOUT
 | 
					 | 
				
			||||||
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 | 
					 | 
				
			||||||
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 | 
					 | 
				
			||||||
 * details.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * You should have received a copy of the GNU General Public License along with
 | 
					 | 
				
			||||||
 * this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * As a special exception, AlliedModders LLC gives you permission to link the
 | 
					 | 
				
			||||||
 * code of this program (as well as its derivative works) to "Half-Life 2," the
 | 
					 | 
				
			||||||
 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
 | 
					 | 
				
			||||||
 * by the Valve Corporation.  You must obey the GNU General Public License in
 | 
					 | 
				
			||||||
 * all respects for all other code used.  Additionally, AlliedModders LLC grants
 | 
					 | 
				
			||||||
 * this exception to all derivative works.  AlliedModders LLC defines further
 | 
					 | 
				
			||||||
 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
 | 
					 | 
				
			||||||
 * or <http://www.sourcemod.net/license.php>.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Version: $Id$
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "ThreadWorker.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ThreadWorker::ThreadWorker(IThreadWorkerCallbacks *hooks) : BaseWorker(hooks),
 | 
					 | 
				
			||||||
	m_Threader(NULL),
 | 
					 | 
				
			||||||
	me(NULL),
 | 
					 | 
				
			||||||
	m_think_time(DEFAULT_THINK_TIME_MS)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	m_state = Worker_Invalid;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ThreadWorker::ThreadWorker(IThreadWorkerCallbacks *hooks, IThreader *pThreader, unsigned int thinktime) : 
 | 
					 | 
				
			||||||
	BaseWorker(hooks),
 | 
					 | 
				
			||||||
	m_Threader(pThreader),
 | 
					 | 
				
			||||||
	me(NULL),
 | 
					 | 
				
			||||||
	m_think_time(thinktime)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	m_state = m_Threader ? Worker_Stopped : Worker_Invalid;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ThreadWorker::~ThreadWorker()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if (m_state != Worker_Stopped || m_state != Worker_Invalid)
 | 
					 | 
				
			||||||
		Stop(true);
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	if (m_ThreadQueue.size())
 | 
					 | 
				
			||||||
		Flush(true);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void ThreadWorker::OnTerminate(IThreadHandle *pHandle, bool cancel)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	//we don't particularly care
 | 
					 | 
				
			||||||
	return;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void ThreadWorker::RunThread(IThreadHandle *pHandle)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if (m_pHooks)
 | 
					 | 
				
			||||||
		m_pHooks->OnWorkerStart(this);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ke::AutoLock lock(&monitor_);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	while (true)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		if (m_state == Worker_Paused)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			// Wait until we're told to wake up.
 | 
					 | 
				
			||||||
			monitor_.Wait();
 | 
					 | 
				
			||||||
			continue;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (m_state == Worker_Stopped)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			// We've been told to stop entirely. If we've also been told to
 | 
					 | 
				
			||||||
			// flush the queue, do that now.
 | 
					 | 
				
			||||||
			while (!m_ThreadQueue.empty())
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				// Release the lock since PopThreadFromQueue() will re-acquire it. The
 | 
					 | 
				
			||||||
				// main thread is blocking anyway.
 | 
					 | 
				
			||||||
				ke::AutoUnlock unlock(&monitor_);
 | 
					 | 
				
			||||||
				RunFrame();
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			assert(m_state == Worker_Stopped);
 | 
					 | 
				
			||||||
			return;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		assert(m_state == Worker_Running);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// Process one frame.
 | 
					 | 
				
			||||||
		WorkerState oldstate = m_state;
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			ke::AutoUnlock unlock(&monitor_);
 | 
					 | 
				
			||||||
			RunFrame();
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// If the state changed, loop back and process the new state.
 | 
					 | 
				
			||||||
		if (m_state != oldstate)
 | 
					 | 
				
			||||||
			continue;
 | 
					 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		// If the thread queue is now empty, wait for a signal. Otherwise, if
 | 
					 | 
				
			||||||
		// we're on a delay, wait for either a notification or a timeout to
 | 
					 | 
				
			||||||
		// process the next item. If the queue has items and we don't have a
 | 
					 | 
				
			||||||
		// delay, then we just loop around and keep processing.
 | 
					 | 
				
			||||||
		if (m_ThreadQueue.empty())
 | 
					 | 
				
			||||||
			monitor_.Wait();
 | 
					 | 
				
			||||||
		else if (m_think_time)
 | 
					 | 
				
			||||||
			monitor_.Wait(m_think_time);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		ke::AutoUnlock unlock(&monitor_);
 | 
					 | 
				
			||||||
		if (m_pHooks)
 | 
					 | 
				
			||||||
			m_pHooks->OnWorkerStop(this);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
SWThreadHandle *ThreadWorker::PopThreadFromQueue()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	ke::AutoLock lock(&monitor_);
 | 
					 | 
				
			||||||
	if (m_state <= Worker_Stopped)
 | 
					 | 
				
			||||||
		return NULL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return BaseWorker::PopThreadFromQueue();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void ThreadWorker::AddThreadToQueue(SWThreadHandle *pHandle)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	ke::AutoLock lock(&monitor_);
 | 
					 | 
				
			||||||
	if (m_state <= Worker_Stopped)
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	BaseWorker::AddThreadToQueue(pHandle);
 | 
					 | 
				
			||||||
	monitor_.Notify();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
WorkerState ThreadWorker::GetStatus(unsigned int *threads)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	ke::AutoLock lock(&monitor_);
 | 
					 | 
				
			||||||
	return BaseWorker::GetStatus(threads);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void ThreadWorker::SetThinkTimePerFrame(unsigned int thinktime)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	m_think_time = thinktime;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
bool ThreadWorker::Start()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if (m_state == Worker_Invalid && m_Threader == NULL)
 | 
					 | 
				
			||||||
		return false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (m_state != Worker_Stopped)
 | 
					 | 
				
			||||||
		return false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	m_state = Worker_Running;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ThreadParams pt;
 | 
					 | 
				
			||||||
	pt.flags = Thread_Default;
 | 
					 | 
				
			||||||
	pt.prio = ThreadPrio_Normal;
 | 
					 | 
				
			||||||
	me = m_Threader->MakeThread(this, &pt);
 | 
					 | 
				
			||||||
	return true;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
bool ThreadWorker::Stop(bool flush_cancel)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	// Change the state to signal a stop, and then trigger a notify.
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		ke::AutoLock lock(&monitor_);
 | 
					 | 
				
			||||||
		if (m_state == Worker_Invalid || m_state == Worker_Stopped)
 | 
					 | 
				
			||||||
			return false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		m_state = Worker_Stopped;
 | 
					 | 
				
			||||||
		m_FlushType = flush_cancel;
 | 
					 | 
				
			||||||
		monitor_.Notify();
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	me->WaitForThread();
 | 
					 | 
				
			||||||
	//destroy it
 | 
					 | 
				
			||||||
	me->DestroyThis();
 | 
					 | 
				
			||||||
	//flush all remaining events
 | 
					 | 
				
			||||||
	Flush(true);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	me = NULL;
 | 
					 | 
				
			||||||
	return true;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
bool ThreadWorker::Pause()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if (m_state != Worker_Running)
 | 
					 | 
				
			||||||
		return false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ke::AutoLock lock(&monitor_);
 | 
					 | 
				
			||||||
	m_state = Worker_Paused;
 | 
					 | 
				
			||||||
	monitor_.Notify();
 | 
					 | 
				
			||||||
	return true;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
bool ThreadWorker::Unpause()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if (m_state != Worker_Paused)
 | 
					 | 
				
			||||||
		return false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ke::AutoLock lock(&monitor_);
 | 
					 | 
				
			||||||
	m_state = Worker_Running;
 | 
					 | 
				
			||||||
	monitor_.Notify();
 | 
					 | 
				
			||||||
	return true;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,69 +0,0 @@
 | 
				
			|||||||
/**
 | 
					 | 
				
			||||||
 * vim: set ts=4 :
 | 
					 | 
				
			||||||
 * =============================================================================
 | 
					 | 
				
			||||||
 * SourceMod
 | 
					 | 
				
			||||||
 * Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
 | 
					 | 
				
			||||||
 * =============================================================================
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * This program is free software; you can redistribute it and/or modify it under
 | 
					 | 
				
			||||||
 * the terms of the GNU General Public License, version 3.0, as published by the
 | 
					 | 
				
			||||||
 * Free Software Foundation.
 | 
					 | 
				
			||||||
 * 
 | 
					 | 
				
			||||||
 * This program is distributed in the hope that it will be useful, but WITHOUT
 | 
					 | 
				
			||||||
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 | 
					 | 
				
			||||||
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 | 
					 | 
				
			||||||
 * details.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * You should have received a copy of the GNU General Public License along with
 | 
					 | 
				
			||||||
 * this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * As a special exception, AlliedModders LLC gives you permission to link the
 | 
					 | 
				
			||||||
 * code of this program (as well as its derivative works) to "Half-Life 2," the
 | 
					 | 
				
			||||||
 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
 | 
					 | 
				
			||||||
 * by the Valve Corporation.  You must obey the GNU General Public License in
 | 
					 | 
				
			||||||
 * all respects for all other code used.  Additionally, AlliedModders LLC grants
 | 
					 | 
				
			||||||
 * this exception to all derivative works.  AlliedModders LLC defines further
 | 
					 | 
				
			||||||
 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
 | 
					 | 
				
			||||||
 * or <http://www.sourcemod.net/license.php>.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Version: $Id$
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifndef _INCLUDE_SOURCEMOD_THREADWORKER_H
 | 
					 | 
				
			||||||
#define _INCLUDE_SOURCEMOD_THREADWORKER_H
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "BaseWorker.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define DEFAULT_THINK_TIME_MS	20
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class ThreadWorker : public BaseWorker, public IThread
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
public:
 | 
					 | 
				
			||||||
	ThreadWorker(IThreadWorkerCallbacks *hooks);
 | 
					 | 
				
			||||||
	ThreadWorker(IThreadWorkerCallbacks *hooks, IThreader *pThreader, unsigned int thinktime=DEFAULT_THINK_TIME_MS);
 | 
					 | 
				
			||||||
	virtual ~ThreadWorker();
 | 
					 | 
				
			||||||
public:	//IThread
 | 
					 | 
				
			||||||
	virtual void OnTerminate(IThreadHandle *pHandle, bool cancel);
 | 
					 | 
				
			||||||
	virtual void RunThread(IThreadHandle *pHandle);
 | 
					 | 
				
			||||||
public:	//IWorker
 | 
					 | 
				
			||||||
	//Controls the worker
 | 
					 | 
				
			||||||
	virtual bool Pause();
 | 
					 | 
				
			||||||
	virtual bool Unpause();
 | 
					 | 
				
			||||||
	virtual bool Start();
 | 
					 | 
				
			||||||
	virtual bool Stop(bool flush_cancel);
 | 
					 | 
				
			||||||
	//returns status and number of threads in queue
 | 
					 | 
				
			||||||
	virtual WorkerState GetStatus(unsigned int *numThreads);
 | 
					 | 
				
			||||||
	//virtual void SetMaxThreadsPerFrame(unsigned int threads);
 | 
					 | 
				
			||||||
	virtual void SetThinkTimePerFrame(unsigned int thinktime);
 | 
					 | 
				
			||||||
public:	//BaseWorker
 | 
					 | 
				
			||||||
	virtual void AddThreadToQueue(SWThreadHandle *pHandle);
 | 
					 | 
				
			||||||
	virtual SWThreadHandle *PopThreadFromQueue();
 | 
					 | 
				
			||||||
protected:
 | 
					 | 
				
			||||||
	IThreader *m_Threader;
 | 
					 | 
				
			||||||
	IThreadHandle *me;
 | 
					 | 
				
			||||||
	unsigned int m_think_time;
 | 
					 | 
				
			||||||
	bool m_FlushType;
 | 
					 | 
				
			||||||
	ke::ConditionVariable monitor_;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif //_INCLUDE_SOURCEMOD_THREADWORKER_H
 | 
					 | 
				
			||||||
@ -1,216 +0,0 @@
 | 
				
			|||||||
/**
 | 
					 | 
				
			||||||
 * vim: set ts=4 sw=4 tw=99 noet:
 | 
					 | 
				
			||||||
 * =============================================================================
 | 
					 | 
				
			||||||
 * SourceMod
 | 
					 | 
				
			||||||
 * Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
 | 
					 | 
				
			||||||
 * =============================================================================
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * This program is free software; you can redistribute it and/or modify it under
 | 
					 | 
				
			||||||
 * the terms of the GNU General Public License, version 3.0, as published by the
 | 
					 | 
				
			||||||
 * Free Software Foundation.
 | 
					 | 
				
			||||||
 * 
 | 
					 | 
				
			||||||
 * This program is distributed in the hope that it will be useful, but WITHOUT
 | 
					 | 
				
			||||||
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 | 
					 | 
				
			||||||
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 | 
					 | 
				
			||||||
 * details.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * You should have received a copy of the GNU General Public License along with
 | 
					 | 
				
			||||||
 * this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * As a special exception, AlliedModders LLC gives you permission to link the
 | 
					 | 
				
			||||||
 * code of this program (as well as its derivative works) to "Half-Life 2," the
 | 
					 | 
				
			||||||
 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
 | 
					 | 
				
			||||||
 * by the Valve Corporation.  You must obey the GNU General Public License in
 | 
					 | 
				
			||||||
 * all respects for all other code used.  Additionally, AlliedModders LLC grants
 | 
					 | 
				
			||||||
 * this exception to all derivative works.  AlliedModders LLC defines further
 | 
					 | 
				
			||||||
 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
 | 
					 | 
				
			||||||
 * or <http://www.sourcemod.net/license.php>.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Version: $Id$
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define _WIN32_WINNT 0x0400
 | 
					 | 
				
			||||||
#include "WinThreads.h"
 | 
					 | 
				
			||||||
#include "ThreadWorker.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
IThreadWorker *WinThreader::MakeWorker(IThreadWorkerCallbacks *hooks, bool threaded)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if (threaded)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		return new ThreadWorker(hooks, this, DEFAULT_THINK_TIME_MS);
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		return new BaseWorker(hooks);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void WinThreader::DestroyWorker(IThreadWorker *pWorker)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	delete pWorker;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void WinThreader::ThreadSleep(unsigned int ms)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	Sleep((DWORD)ms);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
IMutex *WinThreader::MakeMutex()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return new CompatMutex();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
IThreadHandle *WinThreader::MakeThread(IThread *pThread, ThreadFlags flags)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	ThreadParams defparams;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	defparams.flags = flags;
 | 
					 | 
				
			||||||
	defparams.prio = ThreadPrio_Normal;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return MakeThread(pThread, &defparams);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void WinThreader::MakeThread(IThread *pThread)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	ThreadParams defparams;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	defparams.flags = Thread_AutoRelease;
 | 
					 | 
				
			||||||
	defparams.prio = ThreadPrio_Normal;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	MakeThread(pThread, &defparams);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void WinThreader::ThreadHandle::Run()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	// Wait for an unpause if necessary.
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		ke::AutoLock lock(&suspend_);
 | 
					 | 
				
			||||||
		if (m_state == Thread_Paused)
 | 
					 | 
				
			||||||
			suspend_.Wait();
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	m_run->RunThread(this);
 | 
					 | 
				
			||||||
	m_state = Thread_Done;
 | 
					 | 
				
			||||||
	m_run->OnTerminate(this, false);
 | 
					 | 
				
			||||||
	if (m_params.flags & Thread_AutoRelease)
 | 
					 | 
				
			||||||
		delete this;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void WinThreader::GetPriorityBounds(ThreadPriority &max, ThreadPriority &min)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	max = ThreadPrio_Maximum;
 | 
					 | 
				
			||||||
	min = ThreadPrio_Minimum;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ThreadParams g_defparams;
 | 
					 | 
				
			||||||
IThreadHandle *WinThreader::MakeThread(IThread *pThread, const ThreadParams *params)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if (params == NULL)
 | 
					 | 
				
			||||||
		params = &g_defparams;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ThreadHandle* pHandle = new ThreadHandle(this, pThread, params);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	pHandle->m_thread = new ke::Thread([pHandle]() -> void {
 | 
					 | 
				
			||||||
		pHandle->Run();
 | 
					 | 
				
			||||||
	}, "SourceMod");
 | 
					 | 
				
			||||||
	if (!pHandle->m_thread->Succeeded()) {
 | 
					 | 
				
			||||||
		delete pHandle;
 | 
					 | 
				
			||||||
		return nullptr;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (pHandle->m_params.prio != ThreadPrio_Normal)
 | 
					 | 
				
			||||||
		pHandle->SetPriority(pHandle->m_params.prio);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (!(params->flags & Thread_CreateSuspended))
 | 
					 | 
				
			||||||
		pHandle->Unpause();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return pHandle;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
IEventSignal *WinThreader::MakeEventSignal()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return new CompatCondVar();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/******************
 | 
					 | 
				
			||||||
 * Thread Handles *
 | 
					 | 
				
			||||||
 ******************/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
WinThreader::ThreadHandle::ThreadHandle(IThreader *parent, IThread *run, const ThreadParams *params) : 
 | 
					 | 
				
			||||||
	m_parent(parent), m_run(run), m_params(*params),
 | 
					 | 
				
			||||||
	m_state(Thread_Paused)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
WinThreader::ThreadHandle::~ThreadHandle()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
bool WinThreader::ThreadHandle::WaitForThread()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if (!m_thread)
 | 
					 | 
				
			||||||
		return false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	m_thread->Join();
 | 
					 | 
				
			||||||
	return true;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ThreadState WinThreader::ThreadHandle::GetState()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return m_state;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
IThreadCreator *WinThreader::ThreadHandle::Parent()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return m_parent;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void WinThreader::ThreadHandle::DestroyThis()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if (m_params.flags & Thread_AutoRelease)
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	delete this;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void WinThreader::ThreadHandle::GetParams(ThreadParams *ptparams)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if (!ptparams)
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	*ptparams = m_params;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ThreadPriority WinThreader::ThreadHandle::GetPriority()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	return m_params.prio;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
bool WinThreader::ThreadHandle::SetPriority(ThreadPriority prio)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	BOOL res = FALSE;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (prio >= ThreadPrio_Maximum)
 | 
					 | 
				
			||||||
		res = SetThreadPriority(m_thread->handle(), THREAD_PRIORITY_HIGHEST);
 | 
					 | 
				
			||||||
	else if (prio <= ThreadPrio_Minimum)
 | 
					 | 
				
			||||||
		res = SetThreadPriority(m_thread->handle(), THREAD_PRIORITY_LOWEST);
 | 
					 | 
				
			||||||
	else if (prio == ThreadPrio_Normal)
 | 
					 | 
				
			||||||
		res = SetThreadPriority(m_thread->handle(), THREAD_PRIORITY_NORMAL);
 | 
					 | 
				
			||||||
	else if (prio == ThreadPrio_High)
 | 
					 | 
				
			||||||
		res = SetThreadPriority(m_thread->handle(), THREAD_PRIORITY_ABOVE_NORMAL);
 | 
					 | 
				
			||||||
	else if (prio == ThreadPrio_Low)
 | 
					 | 
				
			||||||
		res = SetThreadPriority(m_thread->handle(), THREAD_PRIORITY_BELOW_NORMAL);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	m_params.prio = prio;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return (res != FALSE);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
bool WinThreader::ThreadHandle::Unpause()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if (m_state != Thread_Paused)
 | 
					 | 
				
			||||||
		return false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ke::AutoLock lock(&suspend_);
 | 
					 | 
				
			||||||
	m_state = Thread_Running;
 | 
					 | 
				
			||||||
	suspend_.Notify();
 | 
					 | 
				
			||||||
	return true;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,88 +0,0 @@
 | 
				
			|||||||
/**
 | 
					 | 
				
			||||||
 * vim: set ts=4 :
 | 
					 | 
				
			||||||
 * =============================================================================
 | 
					 | 
				
			||||||
 * SourceMod
 | 
					 | 
				
			||||||
 * Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
 | 
					 | 
				
			||||||
 * =============================================================================
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * This program is free software; you can redistribute it and/or modify it under
 | 
					 | 
				
			||||||
 * the terms of the GNU General Public License, version 3.0, as published by the
 | 
					 | 
				
			||||||
 * Free Software Foundation.
 | 
					 | 
				
			||||||
 * 
 | 
					 | 
				
			||||||
 * This program is distributed in the hope that it will be useful, but WITHOUT
 | 
					 | 
				
			||||||
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 | 
					 | 
				
			||||||
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 | 
					 | 
				
			||||||
 * details.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * You should have received a copy of the GNU General Public License along with
 | 
					 | 
				
			||||||
 * this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * As a special exception, AlliedModders LLC gives you permission to link the
 | 
					 | 
				
			||||||
 * code of this program (as well as its derivative works) to "Half-Life 2," the
 | 
					 | 
				
			||||||
 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
 | 
					 | 
				
			||||||
 * by the Valve Corporation.  You must obey the GNU General Public License in
 | 
					 | 
				
			||||||
 * all respects for all other code used.  Additionally, AlliedModders LLC grants
 | 
					 | 
				
			||||||
 * this exception to all derivative works.  AlliedModders LLC defines further
 | 
					 | 
				
			||||||
 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
 | 
					 | 
				
			||||||
 * or <http://www.sourcemod.net/license.php>.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Version: $Id$
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifndef _INCLUDE_WINTHREADS_H_
 | 
					 | 
				
			||||||
#define _INCLUDE_WINTHREADS_H_
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include <am-thread-utils.h>
 | 
					 | 
				
			||||||
#include <am-utility.h>
 | 
					 | 
				
			||||||
#include <windows.h>
 | 
					 | 
				
			||||||
#include "IThreader.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
using namespace SourceMod;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class WinThreader : public IThreader
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
public:
 | 
					 | 
				
			||||||
	class ThreadHandle : public IThreadHandle
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		friend class WinThreader;
 | 
					 | 
				
			||||||
		friend DWORD WINAPI Win32_ThreadGate(LPVOID param);
 | 
					 | 
				
			||||||
	public:
 | 
					 | 
				
			||||||
		ThreadHandle(IThreader *parent, IThread *run, const ThreadParams *params);
 | 
					 | 
				
			||||||
		virtual ~ThreadHandle();
 | 
					 | 
				
			||||||
	public:
 | 
					 | 
				
			||||||
		virtual bool WaitForThread();
 | 
					 | 
				
			||||||
		virtual void DestroyThis();
 | 
					 | 
				
			||||||
		virtual IThreadCreator *Parent();
 | 
					 | 
				
			||||||
		virtual void GetParams(ThreadParams *ptparams);
 | 
					 | 
				
			||||||
		virtual ThreadPriority GetPriority();
 | 
					 | 
				
			||||||
		virtual bool SetPriority(ThreadPriority prio);
 | 
					 | 
				
			||||||
		virtual ThreadState GetState();
 | 
					 | 
				
			||||||
		virtual bool Unpause();
 | 
					 | 
				
			||||||
		virtual void Run();
 | 
					 | 
				
			||||||
	protected:
 | 
					 | 
				
			||||||
		IThreader *m_parent;		//Parent handle
 | 
					 | 
				
			||||||
		ke::AutoPtr<ke::Thread> m_thread;
 | 
					 | 
				
			||||||
		ThreadParams m_params;		//Current Parameters
 | 
					 | 
				
			||||||
		IThread *m_run;				//Runnable context
 | 
					 | 
				
			||||||
		ThreadState m_state;		//internal state
 | 
					 | 
				
			||||||
		ke::ConditionVariable suspend_;
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
public:
 | 
					 | 
				
			||||||
	IMutex *MakeMutex();
 | 
					 | 
				
			||||||
	void MakeThread(IThread *pThread);
 | 
					 | 
				
			||||||
	IThreadHandle *MakeThread(IThread *pThread, ThreadFlags flags);
 | 
					 | 
				
			||||||
	IThreadHandle *MakeThread(IThread *pThread, const ThreadParams *params);
 | 
					 | 
				
			||||||
	void GetPriorityBounds(ThreadPriority &max, ThreadPriority &min);
 | 
					 | 
				
			||||||
	void ThreadSleep(unsigned int ms);
 | 
					 | 
				
			||||||
	IEventSignal *MakeEventSignal();
 | 
					 | 
				
			||||||
	IThreadWorker *MakeWorker(IThreadWorkerCallbacks *hooks, bool threaded);
 | 
					 | 
				
			||||||
	void DestroyWorker(IThreadWorker *pWorker);
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#if defined SM_DEFAULT_THREADER && !defined SM_MAIN_THREADER
 | 
					 | 
				
			||||||
#define SM_MAIN_THREADER WinThreader;
 | 
					 | 
				
			||||||
typedef class WinThreader MainThreader;
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif //_INCLUDE_WINTHREADS_H_
 | 
					 | 
				
			||||||
@ -1,5 +1,5 @@
 | 
				
			|||||||
/**
 | 
					/**
 | 
				
			||||||
 * vim: set ts=4 :
 | 
					 * vim: set ts=4 sw=4 tw=99 noet :
 | 
				
			||||||
 * =============================================================================
 | 
					 * =============================================================================
 | 
				
			||||||
 * SourceMod
 | 
					 * SourceMod
 | 
				
			||||||
 * Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
 | 
					 * Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
 | 
				
			||||||
@ -273,7 +273,9 @@ namespace SourceMod
 | 
				
			|||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * @brief Describes a simple "condition variable"/signal lock.
 | 
						 * @brief Object that can be used to signal from one thread to another.
 | 
				
			||||||
 | 
						 * This should not be used and is deprecated. Use C++11
 | 
				
			||||||
 | 
						 * std::condition_variable instead, as this version is fundamentally racy.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	class IEventSignal
 | 
						class IEventSignal
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
@ -326,7 +328,7 @@ namespace SourceMod
 | 
				
			|||||||
		 * @return			Number of tasks processed.
 | 
							 * @return			Number of tasks processed.
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		virtual unsigned int RunFrame() =0;
 | 
							virtual unsigned int RunFrame() =0;
 | 
				
			||||||
	public:
 | 
					
 | 
				
			||||||
		/**
 | 
							/**
 | 
				
			||||||
		 * @brief Pauses the worker.
 | 
							 * @brief Pauses the worker.
 | 
				
			||||||
		 *
 | 
							 *
 | 
				
			||||||
@ -446,9 +448,9 @@ namespace SourceMod
 | 
				
			|||||||
		virtual void ThreadSleep(unsigned int ms) =0;
 | 
							virtual void ThreadSleep(unsigned int ms) =0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/**
 | 
							/**
 | 
				
			||||||
		 * @brief Creates a non-signalled event.
 | 
							 * @brief Deprecated; do not use.
 | 
				
			||||||
		 *
 | 
							 *
 | 
				
			||||||
		 * @return			A new IEventSignal pointer (must be destroyed).
 | 
							 * @return			Returns a new IEventSignal.
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		virtual IEventSignal *MakeEventSignal() =0;
 | 
							virtual IEventSignal *MakeEventSignal() =0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										2
									
								
								tools/checkout-deps.sh
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								tools/checkout-deps.sh
									
									
									
									
										vendored
									
									
								
							@ -136,7 +136,7 @@ if [ $? -eq 1 ]; then
 | 
				
			|||||||
  checkout
 | 
					  checkout
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  cd ambuild
 | 
					  cd ambuild
 | 
				
			||||||
  if [ $iswin -eq 1 ]; then
 | 
					  if [ $iswin -eq 1 ] || [ $ismac -eq 1 ]; then
 | 
				
			||||||
    python setup.py install
 | 
					    python setup.py install
 | 
				
			||||||
  else
 | 
					  else
 | 
				
			||||||
    python setup.py build
 | 
					    python setup.py build
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user