Class: WEEL::DSLRealization
- Inherits:
-
Object
- Object
- WEEL::DSLRealization
- Defined in:
- lib/weel.rb
Overview
}}}
Instance Attribute Summary collapse
-
#__weel_connectionwrapper ⇒ Object
}}}.
-
#__weel_connectionwrapper_args ⇒ Object
}}}.
-
#__weel_data ⇒ Object
}}}.
-
#__weel_endpoints ⇒ Object
}}}.
-
#__weel_main ⇒ Object
}}}.
-
#__weel_positions ⇒ Object
}}}.
-
#__weel_replay ⇒ Object
}}}.
-
#__weel_search_positions ⇒ Object
}}}.
-
#__weel_state ⇒ Object
Returns the value of attribute __weel_state.
-
#__weel_status ⇒ Object
readonly
Returns the value of attribute __weel_status.
Instance Method Summary collapse
-
#__weel_finalize ⇒ Object
{{{.
-
#alternative(condition, args = {}, &block) ⇒ Object
Defines a possible choice of a choose-Construct Block is executed if condition == true or searchmode is active (to find the starting position).
-
#call(position, endpoint, parameters: {}, finalize: nil, update: nil, prepare: nil, salvage: nil, &finalizeblk) ⇒ Object
DSL-Constructs for atomic calls to external services (calls) and pure context manipulations (manipulate).
-
#choose(mode = :inclusive, &block) ⇒ Object
Choose DSL-Construct Defines a choice in the Workflow path.
-
#critical(id, &block) ⇒ Object
Defines a critical block (=Mutex).
-
#data ⇒ Object
}}}.
-
#endpoints ⇒ Object
}}}.
-
#escape ⇒ Object
}}}.
-
#initialize ⇒ DSLRealization
constructor
{{{.
-
#loop(condition, args = {}, &block) ⇒ Object
Defines a Cycle (loop/iteration).
-
#manipulate(position, parameters = nil, script = nil, &scriptblk) ⇒ Object
when two params, second param always script when block and two params, parameters stays.
-
#otherwise(args = {}, &block) ⇒ Object
}}}.
-
#parallel(type = nil, &block) ⇒ Object
Parallel DSL-Construct Defines Workflow paths that can be executed parallel.
-
#parallel_branch(*vars, &block) ⇒ Object
Defines a branch of a parallel-Construct.
-
#post_test(code = nil, &blk) ⇒ Object
}}}.
-
#pre_test(code = nil, &blk) ⇒ Object
}}}.
-
#status ⇒ Object
}}}.
-
#stop(position) ⇒ Object
}}}.
-
#terminate ⇒ Object
}}}.
-
#test(code = nil, &blk) ⇒ Object
}}}.
Constructor Details
#initialize ⇒ DSLRealization
{{{
453 454 455 456 457 458 459 460 461 462 463 464 465 |
# File 'lib/weel.rb', line 453 def initialize #{{{ @__weel_search_positions = {} @__weel_positions = Array.new @__weel_main = nil @__weel_data ||= Hash.new @__weel_endpoints ||= Hash.new @__weel_connectionwrapper = ConnectionWrapperBase @__weel_connectionwrapper_args = [] @__weel_state = :ready @__weel_status = Status.new(0,"undefined") @__weel_replay = false @__weel_sim = -1 end |
Instance Attribute Details
#__weel_connectionwrapper ⇒ Object
}}}
466 467 468 |
# File 'lib/weel.rb', line 466 def __weel_connectionwrapper @__weel_connectionwrapper end |
#__weel_connectionwrapper_args ⇒ Object
}}}
466 467 468 |
# File 'lib/weel.rb', line 466 def __weel_connectionwrapper_args @__weel_connectionwrapper_args end |
#__weel_data ⇒ Object
}}}
466 467 468 |
# File 'lib/weel.rb', line 466 def __weel_data @__weel_data end |
#__weel_endpoints ⇒ Object
}}}
466 467 468 |
# File 'lib/weel.rb', line 466 def __weel_endpoints @__weel_endpoints end |
#__weel_main ⇒ Object
}}}
466 467 468 |
# File 'lib/weel.rb', line 466 def __weel_main @__weel_main end |
#__weel_positions ⇒ Object
}}}
466 467 468 |
# File 'lib/weel.rb', line 466 def __weel_positions @__weel_positions end |
#__weel_replay ⇒ Object
}}}
466 467 468 |
# File 'lib/weel.rb', line 466 def __weel_replay @__weel_replay end |
#__weel_search_positions ⇒ Object
}}}
466 467 468 |
# File 'lib/weel.rb', line 466 def __weel_search_positions @__weel_search_positions end |
#__weel_state ⇒ Object
Returns the value of attribute __weel_state.
467 468 469 |
# File 'lib/weel.rb', line 467 def __weel_state @__weel_state end |
#__weel_status ⇒ Object (readonly)
Returns the value of attribute __weel_status.
467 468 469 |
# File 'lib/weel.rb', line 467 def __weel_status @__weel_status end |
Instance Method Details
#__weel_finalize ⇒ Object
{{{
1088 1089 1090 1091 1092 |
# File 'lib/weel.rb', line 1088 def __weel_finalize #{{{ __weel_recursive_join(@__weel_main) @__weel_state = :stopped @__weel_connectionwrapper::inform_state_change @__weel_connectionwrapper_args, @__weel_state end |
#alternative(condition, args = {}, &block) ⇒ Object
Defines a possible choice of a choose-Construct Block is executed if condition == true or searchmode is active (to find the starting position)
628 629 630 631 632 633 634 635 636 637 638 639 640 641 |
# File 'lib/weel.rb', line 628 def alternative(condition,args={},&block)# {{{ return if self.__weel_state == :stopping || self.__weel_state == :finishing || self.__weel_state == :stopped || Thread.current[:nolongernecessary] hw, pos = __weel_sim_start(:alternative,args.merge(:mode => Thread.current[:alternative_mode].last, :condition => ((condition.is_a?(String) || condition.is_a?(Proc)) ? condition : nil))) if __weel_sim Thread.current[:mutex] ||= Mutex.new Thread.current[:mutex].synchronize do return if Thread.current[:alternative_mode][-1] == :exclusive && Thread.current[:alternative_executed][-1] == true if (condition.is_a?(String) || condition.is_a?(Proc)) && !__weel_sim condition = __weel_eval_condition(condition) end Thread.current[:alternative_executed][-1] = true if condition end __weel_protect_yield(&block) if __weel_is_in_search_mode || __weel_sim || condition __weel_sim_stop(:alternative,hw,pos,args.merge(:mode => Thread.current[:alternative_mode].last, :condition => ((condition.is_a?(String) || condition.is_a?(Proc)) ? condition : nil))) if __weel_sim end |
#call(position, endpoint, parameters: {}, finalize: nil, update: nil, prepare: nil, salvage: nil, &finalizeblk) ⇒ Object
DSL-Constructs for atomic calls to external services (calls) and pure context manipulations (manipulate). Calls can also manipulate context (after the invoking the external services) position: a unique identifier within the wf-description (may be used by the search to identify a starting point) endpoint: (only with :call) ep of the service parameters: (only with :call) service parameters
474 475 476 |
# File 'lib/weel.rb', line 474 def call(position, endpoint, parameters: {}, finalize: nil, update: nil, prepare: nil, salvage: nil, &finalizeblk) #{{{ __weel_activity(position,:call,endpoint,parameters,finalize||finalizeblk,update,prepare,salvage) end |
#choose(mode = :inclusive, &block) ⇒ Object
Choose DSL-Construct Defines a choice in the Workflow path. May contain multiple execution alternatives
611 612 613 614 615 616 617 618 619 620 621 622 623 |
# File 'lib/weel.rb', line 611 def choose(mode=:inclusive,&block) # {{{ return if self.__weel_state == :stopping || self.__weel_state == :finishing || self.__weel_state == :stopped || Thread.current[:nolongernecessary] Thread.current[:alternative_executed] ||= [] Thread.current[:alternative_mode] ||= [] Thread.current[:alternative_executed] << false Thread.current[:alternative_mode] << mode hw, pos = __weel_sim_start(:choose,:mode => Thread.current[:alternative_mode].last) if __weel_sim __weel_protect_yield(&block) __weel_sim_stop(:choose,hw,pos,:mode => Thread.current[:alternative_mode].last) if __weel_sim Thread.current[:alternative_executed].pop Thread.current[:alternative_mode].pop nil end |
#critical(id, &block) ⇒ Object
Defines a critical block (=Mutex)
650 651 652 653 654 655 656 657 658 659 660 661 |
# File 'lib/weel.rb', line 650 def critical(id,&block)# {{{ @__weel_critical ||= Mutex.new semaphore = nil @__weel_critical.synchronize do @__weel_critical_sections ||= {} semaphore = @__weel_critical_sections[id] ? @__weel_critical_sections[id] : Mutex.new @__weel_critical_sections[id] = semaphore if id end semaphore.synchronize do __weel_protect_yield(&block) end end |
#data ⇒ Object
}}}
748 749 750 |
# File 'lib/weel.rb', line 748 def data # {{{ ReadOnlyHash.new(@__weel_data,__weel_sim) end |
#endpoints ⇒ Object
}}}
751 752 753 |
# File 'lib/weel.rb', line 751 def endpoints # {{{ ReadHash.new(@__weel_endpoints) end |
#escape ⇒ Object
}}}
720 721 722 723 724 |
# File 'lib/weel.rb', line 720 def escape #{{{ return if __weel_is_in_search_mode return if self.__weel_state == :stopping || self.__weel_state == :finishing || self.__weel_state == :stopped || Thread.current[:nolongernecessary] throw :escape end |
#loop(condition, args = {}, &block) ⇒ Object
Defines a Cycle (loop/iteration)
664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 |
# File 'lib/weel.rb', line 664 def loop(condition,args={},&block)# {{{ unless condition.is_a?(Array) && (condition[0].is_a?(Proc) || condition[0].is_a?(String)) && [:pre_test,:post_test].include?(condition[1]) && args.is_a?(Hash) raise "condition must be called pre_test{} or post_test{}" end return if self.__weel_state == :stopping || self.__weel_state == :finishing || self.__weel_state == :stopped || Thread.current[:nolongernecessary] if __weel_is_in_search_mode catch :escape do __weel_protect_yield(&block) end if __weel_is_in_search_mode return else ### in case it was a :post_test we wake inside the loop so we can check ### condition first thing condition[1] = :pre_test end end if __weel_sim cond = condition[0].is_a?(Proc) ? true : condition[0] hw, pos = __weel_sim_start(:loop,args.merge(:testing=>condition[1],:condition=>cond)) catch :escape do __weel_protect_yield(&block) end __weel_sim_stop(:loop,hw,pos,args.merge(:testing=>condition[1],:condition=>cond)) return end loop_guard = 0 loop_id = SecureRandom.uuid catch :escape do case condition[1] when :pre_test while __weel_eval_condition(condition[0]) && self.__weel_state != :stopping && self.__weel_state != :stopped && self.__weel_state != :finishing && !Thread.current[:nolongernecessary] loop_guard += 1 __weel_protect_yield(&block) sleep 1 if @__weel_connectionwrapper::loop_guard(@__weel_connectionwrapper_args,loop_id,loop_guard) end when :post_test begin loop_guard += 1 __weel_protect_yield(&block) sleep 1 if @__weel_connectionwrapper::loop_guard(@__weel_connectionwrapper_args,loop_id,loop_guard) end while __weel_eval_condition(condition[0]) && self.__weel_state != :stopping && self.__weel_state != :stopped && self.__weel_state != :finishing && !Thread.current[:nolongernecessary] end end end |
#manipulate(position, parameters = nil, script = nil, &scriptblk) ⇒ Object
when two params, second param always script when block and two params, parameters stays
479 480 481 482 483 484 |
# File 'lib/weel.rb', line 479 def manipulate(position, parameters=nil, script=nil, &scriptblk) #{{{ if scriptblk.nil? && script.nil? && !parameters.nil? script, parameters = parameters, nil end __weel_activity(position,:manipulate,nil,parameters||{},script||scriptblk) end |
#otherwise(args = {}, &block) ⇒ Object
}}}
642 643 644 645 646 647 |
# File 'lib/weel.rb', line 642 def otherwise(args={},&block) # {{{ return if self.__weel_state == :stopping || self.__weel_state == :finishing || self.__weel_state == :stopped || Thread.current[:nolongernecessary] hw, pos = __weel_sim_start(:otherwise,args.merge(:mode => Thread.current[:alternative_mode].last)) if __weel_sim __weel_protect_yield(&block) if __weel_is_in_search_mode || __weel_sim || !Thread.current[:alternative_executed].last __weel_sim_stop(:otherwise,hw,pos,args.merge(:mode => Thread.current[:alternative_mode].last)) if __weel_sim end |
#parallel(type = nil, &block) ⇒ Object
Parallel DSL-Construct Defines Workflow paths that can be executed parallel. May contain multiple branches (parallel_branch)
489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 |
# File 'lib/weel.rb', line 489 def parallel(type=nil,&block)# {{{ return if self.__weel_state == :stopping || self.__weel_state == :finishing || self.__weel_state == :stopped Thread.current[:branches] = [] Thread.current[:branch_traces] = {} Thread.current[:branch_traces_ids] = 0 Thread.current[:branch_finished_count] = 0 Thread.current[:branch_event] = Continue.new Thread.current[:mutex] = Mutex.new hw, pos = __weel_sim_start(:parallel) if __weel_sim __weel_protect_yield(&block) Thread.current[:branch_wait_count] = (type.is_a?(Hash) && type[:wait] != nil && (type[:wait].is_a?(Integer) && type[:wait] > 0) ? type[:wait] : Thread.current[:branches].size) Thread.current[:branch_wait_count_cancel] = 0 Thread.current[:branch_wait_count_cancel_condition] = (type.is_a?(Hash) && type[:cancel] != nil && type[:cancel] == :first ) ? :first : :last 1.upto Thread.current[:branches].size do Thread.current[:branch_event].wait end Thread.current[:branches].each do |thread| # decide after executing block in parallel cause for coopis # it goes out of search mode while dynamically counting branches if Thread.current[:branch_search] == false thread[:branch_search] = false end thread[:start_event]&.continue # sometimes start event might not even exist yet (i.e. race condition) end Thread.current[:branch_event].wait unless self.__weel_state == :stopping || self.__weel_state == :finishing || self.__weel_state == :stopped __weel_sim_stop(:parallel,hw,pos) if __weel_sim cw = @__weel_connectionwrapper.new @__weel_connectionwrapper_args cw.join_branches(Thread.current[:branch_traces]) unless self.__weel_state == :stopping || self.__weel_state == :finishing || self.__weel_state == :stopped # first set all to no_longer_neccessary Thread.current[:branches].each do |thread| if thread.alive? thread[:nolongernecessary] = true __weel_recursive_continue(thread) end end # wait for all Thread.current[:branches].each do |thread| __weel_recursive_join(thread) end end end |
#parallel_branch(*vars, &block) ⇒ Object
Defines a branch of a parallel-Construct
542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 |
# File 'lib/weel.rb', line 542 def parallel_branch(*vars,&block)# {{{ return if self.__weel_state == :stopping || self.__weel_state == :finishing || self.__weel_state == :stopped || Thread.current[:nolongernecessary] branch_parent = Thread.current if __weel_sim # catch the potential execution in loops inside a parallel current_branch_sim_pos = branch_parent[:branch_sim_pos] end branch_parent[:branches] << Thread.new(*vars) do |*local| Thread.current.abort_on_exception = true Thread.current[:branch_status] = false Thread.current[:branch_parent] = branch_parent Thread.current[:start_event] = Continue.new Thread.current[:local] = local Thread.current[:branch_wait_count_cancel_active] = false branch_parent[:mutex].synchronize do Thread.current[:branch_traces_id] = branch_parent[:branch_traces_ids] branch_parent[:branch_traces_ids] += 1 end if __weel_sim Thread.current[:branch_sim_pos] = @__weel_sim += 1 end # parallel_branch could be possibly around an alternative. Thus thread has to inherit the alternative_executed # after branching, update it in the parent (TODO) if branch_parent[:alternative_executed] && branch_parent[:alternative_executed].length > 0 Thread.current[:alternative_executed] = [branch_parent[:alternative_executed].last] Thread.current[:alternative_mode] = [branch_parent[:alternative_mode].last] end branch_parent[:branch_event].continue Thread.current[:start_event].wait unless self.__weel_state == :stopping || self.__weel_state == :stopped || self.__weel_state == :finishing if __weel_sim connectionwrapper = @__weel_connectionwrapper.new @__weel_connectionwrapper_args connectionwrapper.simulate(:parallel_branch,:start,Thread.current[:branch_sim_pos],current_branch_sim_pos) end unless self.__weel_state == :stopping || self.__weel_state == :finishing || self.__weel_state == :stopped || Thread.current[:nolongernecessary] __weel_protect_yield(*local, &block) end __weel_sim_stop(:parallel_branch,connectionwrapper,current_branch_sim_pos) if __weel_sim branch_parent[:mutex].synchronize do Thread.current[:branch_status] = true branch_parent[:branch_finished_count] += 1 if branch_parent[:branch_finished_count] == branch_parent[:branch_wait_count] && self.__weel_state != :stopping && self.__weel_state != :finishing branch_parent[:branch_event].continue end end unless self.__weel_state == :stopping || self.__weel_state == :stopped || self.__weel_state == :finishing if Thread.current[:branch_position] @__weel_positions.delete Thread.current[:branch_position] begin ipc = {} ipc[:unmark] = [Thread.current[:branch_position]] @__weel_connectionwrapper::inform_position_change(@__weel_connectionwrapper_args,ipc) end rescue nil Thread.current[:branch_position] = nil end end end end |
#post_test(code = nil, &blk) ⇒ Object
}}}
716 717 718 |
# File 'lib/weel.rb', line 716 def post_test(code=nil,&blk)# {{{ [code || blk, :post_test] end |
#pre_test(code = nil, &blk) ⇒ Object
}}}
713 714 715 |
# File 'lib/weel.rb', line 713 def pre_test(code=nil,&blk)# {{{ [code || blk, :pre_test] end |
#status ⇒ Object
}}}
745 746 747 |
# File 'lib/weel.rb', line 745 def status # {{{ @__weel_status end |
#stop(position) ⇒ Object
}}}
730 731 732 733 734 735 736 737 738 739 740 741 742 743 |
# File 'lib/weel.rb', line 730 def stop(position) #{{{ searchmode = __weel_is_in_search_mode(position) return if searchmode return if self.__weel_state == :stopping || self.__weel_state == :finishing || self.__weel_state == :stopped || Thread.current[:nolongernecessary] # gather traces in threads to point to join if Thread.current[:branch_parent] && Thread.current[:branch_traces_id] Thread.current[:branch_parent][:branch_traces][Thread.current[:branch_traces_id]] ||= [] Thread.current[:branch_parent][:branch_traces][Thread.current[:branch_traces_id]] << position end __weel_progress position, 0, true self.__weel_state = :stopping end |
#terminate ⇒ Object
}}}
725 726 727 728 729 |
# File 'lib/weel.rb', line 725 def terminate #{{{ return if __weel_is_in_search_mode return if self.__weel_state == :stopping || self.__weel_state == :finishing || self.__weel_state == :stopped || Thread.current[:nolongernecessary] self.__weel_state = :finishing end |
#test(code = nil, &blk) ⇒ Object
}}}
710 711 712 |
# File 'lib/weel.rb', line 710 def test(code=nil,&blk)# {{{ code || blk end |