151c0b2f7Stbbdev#!/usr/bin/env python3 251c0b2f7Stbbdev# 3*2eccd5f9SIlya Isaev# Copyright (c) 2016-2022 Intel Corporation 451c0b2f7Stbbdev# 551c0b2f7Stbbdev# Licensed under the Apache License, Version 2.0 (the "License"); 651c0b2f7Stbbdev# you may not use this file except in compliance with the License. 751c0b2f7Stbbdev# You may obtain a copy of the License at 851c0b2f7Stbbdev# 951c0b2f7Stbbdev# http://www.apache.org/licenses/LICENSE-2.0 1051c0b2f7Stbbdev# 1151c0b2f7Stbbdev# Unless required by applicable law or agreed to in writing, software 1251c0b2f7Stbbdev# distributed under the License is distributed on an "AS IS" BASIS, 1351c0b2f7Stbbdev# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1451c0b2f7Stbbdev# See the License for the specific language governing permissions and 1551c0b2f7Stbbdev# limitations under the License. 1651c0b2f7Stbbdev 1751c0b2f7Stbbdev# Based on the software developed by: 1851c0b2f7Stbbdev# Copyright (c) 2008,2016 david decotigny (Pool of threads) 1951c0b2f7Stbbdev# Copyright (c) 2006-2008, R Oudkerk (multiprocessing.Pool) 2051c0b2f7Stbbdev# All rights reserved. 2151c0b2f7Stbbdev# 2251c0b2f7Stbbdev# Redistribution and use in source and binary forms, with or without 2351c0b2f7Stbbdev# modification, are permitted provided that the following conditions 2451c0b2f7Stbbdev# are met: 2551c0b2f7Stbbdev# 2651c0b2f7Stbbdev# 1. Redistributions of source code must retain the above copyright 2751c0b2f7Stbbdev# notice, this list of conditions and the following disclaimer. 2851c0b2f7Stbbdev# 2. Redistributions in binary form must reproduce the above copyright 2951c0b2f7Stbbdev# notice, this list of conditions and the following disclaimer in the 3051c0b2f7Stbbdev# documentation and/or other materials provided with the distribution. 3151c0b2f7Stbbdev# 3. Neither the name of author nor the names of any contributors may be 3251c0b2f7Stbbdev# used to endorse or promote products derived from this software 3351c0b2f7Stbbdev# without specific prior written permission. 3451c0b2f7Stbbdev# 3551c0b2f7Stbbdev# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND 3651c0b2f7Stbbdev# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 3751c0b2f7Stbbdev# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 3851c0b2f7Stbbdev# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 3951c0b2f7Stbbdev# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 4051c0b2f7Stbbdev# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 4151c0b2f7Stbbdev# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4251c0b2f7Stbbdev# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 4351c0b2f7Stbbdev# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 4451c0b2f7Stbbdev# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 4551c0b2f7Stbbdev# SUCH DAMAGE. 4651c0b2f7Stbbdev# 4751c0b2f7Stbbdev 4851c0b2f7Stbbdevimport time 4951c0b2f7Stbbdevimport threading 5051c0b2f7Stbbdev 5151c0b2f7Stbbdevfrom .api import * 5251c0b2f7Stbbdevfrom .pool import * 5351c0b2f7Stbbdev 5451c0b2f7Stbbdev 5551c0b2f7Stbbdevdef test(arg=None): 5651c0b2f7Stbbdev if arg == "-v": 5751c0b2f7Stbbdev def say(*x): 5851c0b2f7Stbbdev print(*x) 5951c0b2f7Stbbdev else: 6051c0b2f7Stbbdev def say(*x): 6151c0b2f7Stbbdev pass 6251c0b2f7Stbbdev say("Start Pool testing") 6351c0b2f7Stbbdev print("oneTBB version is %s" % runtime_version()) 6451c0b2f7Stbbdev print("oneTBB interface version is %s" % runtime_interface_version()) 6551c0b2f7Stbbdev 6651c0b2f7Stbbdev get_tid = lambda: threading.current_thread().ident 6751c0b2f7Stbbdev 6851c0b2f7Stbbdev assert default_num_threads() == this_task_arena_max_concurrency() 6951c0b2f7Stbbdev 7051c0b2f7Stbbdev def return42(): 7151c0b2f7Stbbdev return 42 7251c0b2f7Stbbdev 7351c0b2f7Stbbdev def f(x): 7451c0b2f7Stbbdev return x * x 7551c0b2f7Stbbdev 7651c0b2f7Stbbdev def work(mseconds): 7751c0b2f7Stbbdev res = str(mseconds) 7851c0b2f7Stbbdev if mseconds < 0: 7951c0b2f7Stbbdev mseconds = -mseconds 8051c0b2f7Stbbdev say("[%d] Start to work for %fms..." % (get_tid(), mseconds*10)) 8151c0b2f7Stbbdev time.sleep(mseconds/100.) 8251c0b2f7Stbbdev say("[%d] Work done (%fms)." % (get_tid(), mseconds*10)) 8351c0b2f7Stbbdev return res 8451c0b2f7Stbbdev 85*2eccd5f9SIlya Isaev # special flag to to be set by thread calling async work 86*2eccd5f9SIlya Isaev spin_flag = None 87*2eccd5f9SIlya Isaev def timeout_work(param): 88*2eccd5f9SIlya Isaev say("[%d] Spin wait work start..." % get_tid()) 89*2eccd5f9SIlya Isaev while spin_flag: 90*2eccd5f9SIlya Isaev time.sleep(0.0001) # yield equivalent 91*2eccd5f9SIlya Isaev say("[%d] Work done." % get_tid()) 92*2eccd5f9SIlya Isaev return str(param) if param != None else None 93*2eccd5f9SIlya Isaev 94*2eccd5f9SIlya Isaev def prepare_timeout_exception(): 95*2eccd5f9SIlya Isaev nonlocal spin_flag 96*2eccd5f9SIlya Isaev spin_flag = True # lock threads in timeout_work 97*2eccd5f9SIlya Isaev 98*2eccd5f9SIlya Isaev def check_timeout_exception(pool_object, func): 99*2eccd5f9SIlya Isaev nonlocal spin_flag 100*2eccd5f9SIlya Isaev try: 101*2eccd5f9SIlya Isaev func(pool_object) 102*2eccd5f9SIlya Isaev except TimeoutError: 103*2eccd5f9SIlya Isaev say("Good. Got expected timeout exception.") 104*2eccd5f9SIlya Isaev else: 105*2eccd5f9SIlya Isaev assert False, "Expected exception !" 106*2eccd5f9SIlya Isaev spin_flag = False # unlock threads in timeout_work 107*2eccd5f9SIlya Isaev 10851c0b2f7Stbbdev ### Test copy/pasted from multiprocessing 10951c0b2f7Stbbdev pool = Pool(4) # start worker threads 11051c0b2f7Stbbdev 11151c0b2f7Stbbdev # edge cases 11251c0b2f7Stbbdev assert pool.map(return42, []) == [] 11351c0b2f7Stbbdev assert pool.apply_async(return42, []).get() == 42 11451c0b2f7Stbbdev assert pool.apply(return42, []) == 42 11551c0b2f7Stbbdev assert list(pool.imap(return42, iter([]))) == [] 11651c0b2f7Stbbdev assert list(pool.imap_unordered(return42, iter([]))) == [] 11751c0b2f7Stbbdev assert pool.map_async(return42, []).get() == [] 11851c0b2f7Stbbdev assert list(pool.imap_async(return42, iter([])).get()) == [] 11951c0b2f7Stbbdev assert list(pool.imap_unordered_async(return42, iter([])).get()) == [] 12051c0b2f7Stbbdev 12151c0b2f7Stbbdev # basic tests 12251c0b2f7Stbbdev result = pool.apply_async(f, (10,)) # evaluate "f(10)" asynchronously 12351c0b2f7Stbbdev assert result.get(timeout=1) == 100 # ... unless slow computer 12451c0b2f7Stbbdev assert list(pool.map(f, range(10))) == list(map(f, range(10))) 12551c0b2f7Stbbdev it = pool.imap(f, range(10)) 12651c0b2f7Stbbdev assert next(it) == 0 12751c0b2f7Stbbdev assert next(it) == 1 12851c0b2f7Stbbdev assert next(it) == 4 12951c0b2f7Stbbdev 13051c0b2f7Stbbdev # Test apply_sync exceptions 131*2eccd5f9SIlya Isaev prepare_timeout_exception() 132*2eccd5f9SIlya Isaev result = pool.apply_async(timeout_work, (None,)) 133*2eccd5f9SIlya Isaev check_timeout_exception(result, lambda result : say(result.get(timeout=1))) 13451c0b2f7Stbbdev assert result.get() is None # sleep() returns None 13551c0b2f7Stbbdev 13651c0b2f7Stbbdev def cb(s): 13751c0b2f7Stbbdev say("Result ready: %s" % s) 13851c0b2f7Stbbdev 13951c0b2f7Stbbdev # Test imap() 14051c0b2f7Stbbdev assert list(pool.imap(work, range(10, 3, -1), chunksize=4)) == list(map( 14151c0b2f7Stbbdev str, range(10, 3, -1))) 14251c0b2f7Stbbdev 14351c0b2f7Stbbdev # Test imap_unordered() 14451c0b2f7Stbbdev assert sorted(pool.imap_unordered(work, range(10, 3, -1))) == sorted(map( 14551c0b2f7Stbbdev str, range(10, 3, -1))) 14651c0b2f7Stbbdev 14751c0b2f7Stbbdev # Test map_async() 148*2eccd5f9SIlya Isaev prepare_timeout_exception() 149*2eccd5f9SIlya Isaev result = pool.map_async(timeout_work, range(10), callback=cb) 150*2eccd5f9SIlya Isaev check_timeout_exception(result, lambda result : result.get(timeout=0.01)) 15151c0b2f7Stbbdev say(result.get()) 15251c0b2f7Stbbdev 15351c0b2f7Stbbdev # Test imap_async() 154*2eccd5f9SIlya Isaev prepare_timeout_exception() 155*2eccd5f9SIlya Isaev result = pool.imap_async(timeout_work, range(3, 10), callback=cb) 156*2eccd5f9SIlya Isaev check_timeout_exception(result, lambda result : result.get(timeout=0.01)) 15751c0b2f7Stbbdev for i in result.get(): 15851c0b2f7Stbbdev say("Item:", i) 15951c0b2f7Stbbdev say("### Loop again:") 16051c0b2f7Stbbdev for i in result.get(): 16151c0b2f7Stbbdev say("Item2:", i) 16251c0b2f7Stbbdev 16351c0b2f7Stbbdev # Test imap_unordered_async() 164*2eccd5f9SIlya Isaev prepare_timeout_exception() 165*2eccd5f9SIlya Isaev result = pool.imap_unordered_async(timeout_work, range(10, 3, -1), callback=cb) 166*2eccd5f9SIlya Isaev check_timeout_exception(result, lambda result : result.get(timeout=0.01)) 16751c0b2f7Stbbdev for i in result.get(): 16851c0b2f7Stbbdev say("Item1:", i) 16951c0b2f7Stbbdev for i in result.get(): 17051c0b2f7Stbbdev say("Item2:", i) 17151c0b2f7Stbbdev r = result.get() 17251c0b2f7Stbbdev for i in r: 17351c0b2f7Stbbdev say("Item3:", i) 17451c0b2f7Stbbdev for i in r: 17551c0b2f7Stbbdev say("Item4:", i) 17651c0b2f7Stbbdev for i in r: 17751c0b2f7Stbbdev say("Item5:", i) 17851c0b2f7Stbbdev 17951c0b2f7Stbbdev # 18051c0b2f7Stbbdev # The case for the exceptions 18151c0b2f7Stbbdev # 18251c0b2f7Stbbdev 18351c0b2f7Stbbdev # Exceptions in imap_unordered_async() 18451c0b2f7Stbbdev result = pool.imap_unordered_async(work, range(2, -10, -1), callback=cb) 18551c0b2f7Stbbdev time.sleep(3) 18651c0b2f7Stbbdev try: 18751c0b2f7Stbbdev for i in result.get(): 18851c0b2f7Stbbdev say("Got item:", i) 18951c0b2f7Stbbdev except (IOError, ValueError): 19051c0b2f7Stbbdev say("Good. Got expected exception") 19151c0b2f7Stbbdev 19251c0b2f7Stbbdev # Exceptions in imap_async() 19351c0b2f7Stbbdev result = pool.imap_async(work, range(2, -10, -1), callback=cb) 19451c0b2f7Stbbdev time.sleep(3) 19551c0b2f7Stbbdev try: 19651c0b2f7Stbbdev for i in result.get(): 19751c0b2f7Stbbdev say("Got item:", i) 19851c0b2f7Stbbdev except (IOError, ValueError): 19951c0b2f7Stbbdev say("Good. Got expected exception") 20051c0b2f7Stbbdev 20151c0b2f7Stbbdev # Stop the test: need to stop the pool !!! 20251c0b2f7Stbbdev pool.terminate() 20351c0b2f7Stbbdev pool.join() 20451c0b2f7Stbbdev 20551c0b2f7Stbbdevif __name__ == "__main__": 20651c0b2f7Stbbdev test() 207