//works 任务分派
import win.guid;
import thread.table;
import thread.semaphore;

namespace thread

class works{
	ctor( limit,func,waitTime,fInit,...){
		this._guid = tostring(..win.guid.create());
		this._thrdWorking = ..thread.var(this._guid + "$working",0) ;
		this._thrdArguments = ..thread.table( this._guid + "$arguments",0); 
		this._thrdResults = ..thread.table( this._guid + "$result",0);   
		this._thrdSign = ..thread.var(this._guid + "$sign",true); 
		this._semaphore = ..thread.semaphore(,limit);

		var threads = {} 
		for(i=1;limit;1){
			var thrd = {}
			thrd.handle,thrd.id = ..thread.create(
				function(semaphore,func,fInit,waitTime,thrdSign,thrdWorking,thrdArguments,thrdResults,...){ 
					if(fInit) fInit(...);
					while( thrdSign.get() ){ 
						if( thrdArguments.len() > 0 ){
							var arg = thrdArguments.remove() 
							if(arg!==null){  
								thrdWorking.add(1);
								var ret = func(arg,...);
								if(ret!==null) thrdResults.insert( ret ); 
								thrdWorking.add(-1);
								semaphore.release();
							}
						}
						else {
							sleep(waitTime);
						} 
					}  
				},this._semaphore,func,fInit,waitTime : 500 
					,this._thrdSign,this._thrdWorking,this._thrdArguments,this._thrdResults
					,...
			)
			..table.push(threads,thrd);
		
		} 
		..table.gc(this,"quit");
	};
	each = function(){
		this.suspend()
		return function(k){
			return this._thrdArguments.next(k);
		},function(){
			this.resume();
		} ;
	};
	update = function(idx,args){
		this._thrdArguments.set(idx,args);
	};
	push = function(...){
		if( #threads ) { 
			if( this._semaphore.waitOne() ){
				this._thrdArguments.push(...);	
			} 
		}
	};
	peek = function(n){ 
		return this._thrdResults.len()
	};
	pop = function(n){ 
		if(this._thrdResults.len()){
			return this._thrdResults.pop(n)	 
		}
	};
	getHandleById = function(id){
		var handles ={}
		for(slot,thrd in threads){
			if( thrd.id = id) return thrd.handle; 
		} 
	};
	getHandles = function(){
		var handles ={}
		for(slot,thrd in threads){
			..table.push( handles,thrd.handle ) //support push null   
		} 
		return handles;	
	};
	suspend = function(id){
		if( id ){ 
			var handle = this.getHandleById(id) ;
			return handle ? ..thread.suspend( handle )
		}
		
		var handles = this.getHandles();
		for(i,hdle in handles){ 
			..thread.suspend(hdle)
		} 
	}; 
	resume = function(id){
		if( id ){ 
			var handle = this.getHandleById(id) ;
			return handle ? ..thread.resume( handle )
		}
		
		var handles = this.getHandles();
		for(i,hdle in handles){ 
			..thread.resume(hdle)
		} 	
	};
	clear = function(){
		this._thrdArguments.clear();
		
		var delay = ..win[["ui"]] ?  ..win[["delay"]] : sleep
		delay(100);  
		while( this._thrdWorking.get() > 0 ) { 
			delay( 100  )
		} 
		this._thrdWorking.set(0);
		this._thrdResults.clear();
	};
	quit = function(){ 
		if( #threads ){ 
			var delay = ..win[["ui"]] ?  ..win[["delay"]] : sleep
			var handles = this.getHandles(); 
			for(i=1;#handles){ 
				..raw.closehandle(handles[i])
			} 
			threads = {};
			this._thrdSign.set(null)
 
			delay(100);  
			while( this._thrdWorking.get() > 0 ) { 
				delay( 100  )
			} 
			this._thrdWorking.set(0);
			this._thrdArguments.clear();
			this._thrdResults.clear();
		}
	};
	queueCount = function(){
		return this._thrdArguments.len();
	};
	busy = function(){
		return ( this._thrdArguments.len() > 0 ||  this._thrdWorking.get()  )
	};
	finished = function(){
		return !this.busy() && !this._thrdResults.len()
	};
	wait = function(f){ 
		var r;
		var delay = ..win[["ui"]] ?  ..win[["delay"]] : sleep;
		while( this.busy() ) { 
			if( ! delay( 100  ) ){
				return;
			}
			if( f ){
				r = this.pop(1);
				if(r!==null)f(r);
			}
		}
		
		if(f){
			r = this.pop(1);
			while( (r!==null) && delay(10) ){
				f(r);
				r = this.pop(1);
			} 
		}
		return true; 
	};
	waitClose = function(f){
		var r = this.wait(f);
		this.quit();
		return r;
	}; 
}  


/**intellisense()
thread.works = 线程工作项管理
thread.works(线程数,工作函数,等待延时,初始化函数,->->->) = @.works( 20,\n	function(arguments,...) {\n		__/*arguments为线程任务传递的参数,\n其他参数为创建thread.work时的附加参数,\n这些附加参数也会传递给初始化函数*/\n		return "返回值"\n	} \n);
thread.works() = !thread_work.
!thread_work.queueCount() = 排队等候执行的任务数目
!thread_work.clear() = 清空已添加的任务
!thread_work.push(__) = 添加调用实参到任务列表尾部\n可使用table对象传递多个参数给任务函数\n工作函数将自动获取参数并执行任务,\n此函数会等待空闲线程,等待时界面线程仍然可以处理窗口消息
!thread_work.pop(__) = 弹出工作函数完成任务后的返回值，\n注意如果线程返回的是null将被忽略
!thread_work.peek() = 是否有线程完成了新的任务并返回了新的值，\n注意如果线程返回的是null将被忽略
!thread_work.quit() =  通知所有线程退出\n并等待线程关闭
!thread_work.wait() =  等待所有任务完成,\n可指定一个回调函数作为参数接收工作项返回值\n\n建议在界面线程使用定时器替代此函数
!thread_work.waitClose() =  等待所有任务完成\n通知所有线程退出,并等待所有线程关闭.\n可指定一个回调函数作为参数接收工作项返回值\n\n建议在界面线程使用定时器替代此函数
!thread_work.busy() = 是否有未完成任务
!thread_work.finished() = 是否有未完成任务或未读取的任务返回值
!thread_work.suspend() = 所有线程暂停\n可选在参数中指定线程ID\n注意线程是否正在使用互斥锁
!thread_work.resume() = 所有线程继续执行\n可选在参数中指定线程ID
!thread_work.getHandleById(.(线程ID) = 使用线程ID返回线程句柄\n不可关闭该句柄
!thread_work.update(.(索引,参数) = 更新任务参数\该函数只能在each循环内部使用
!thread_work.each = @for( idx,args in ??.each() ){
	__/*遍历所有待执行任务,\n该函数会暂停所有任务*/
}
end intellisense**/