public override void main()
        {
            Console.WriteLine(this.ThisFacetInstance + "/" + this.Rank + ": WORKFLOW 1");

            Task_binding_data.TraceFlag = Task_gusty0.TraceFlag = Task_gusty1.TraceFlag = Task_binding_step1.TraceFlag = Task_binding_split_first.TraceFlag = Task_binding_split_next.TraceFlag = true;
            Task_binding_data.TraceFlag = Task_binding_step1.TraceFlag = Task_binding_split_first.TraceFlag = Task_binding_split_next.TraceFlag = true;

            IActionFutureSet future_iteration = null;

            Console.WriteLine(this.ThisFacetInstance + "/" + this.Rank + ": WORKFLOW 2-1");

            IActionFuture future_split_first_chunk_ready = null;

            Task_binding_split_first.invoke(ITaskPortAdvance.CHUNK_READY, out future_split_first_chunk_ready);
            int action_id_split_first_chunk_ready = future_split_first_chunk_ready.GetHashCode();

            future_iteration = future_split_first_chunk_ready.createSet();

            Console.WriteLine(this.ThisFacetInstance + "/" + this.Rank + ": WORKFLOW 2-2");

            IActionFuture future_split_next_chunk_ready = null;

            Task_binding_split_next.invoke(ITaskPortAdvance.CHUNK_READY, out future_split_next_chunk_ready);
            int action_id_split_next_chunk_ready = future_split_next_chunk_ready.GetHashCode();

            future_iteration.addAction(future_split_next_chunk_ready);

            Console.WriteLine(this.ThisFacetInstance + "/" + this.Rank + ": WORKFLOW 3");

            IActionFuture future_gusty0_chunk_ready = null;

            Task_gusty0.invoke(ITaskPortAdvance.CHUNK_READY, out future_gusty0_chunk_ready);
            int action_id_gusty0_chunk_ready = future_gusty0_chunk_ready.GetHashCode();

            future_iteration.addAction(future_gusty0_chunk_ready);

            Console.WriteLine(this.ThisFacetInstance + "/" + this.Rank + ": WORKFLOW 4");

            IActionFuture future_step1_chunk_ready = null;

            Task_binding_step1.invoke(ITaskPortAdvance.CHUNK_READY, out future_step1_chunk_ready);
            int action_id_step1_chunk_ready = future_step1_chunk_ready.GetHashCode();

            future_iteration.addAction(future_step1_chunk_ready);

            Console.WriteLine(this.ThisFacetInstance + "/" + this.Rank + ": WORKFLOW 4");

            IActionFuture future_gusty1_chunk_ready = null;

            Task_gusty1.invoke(ITaskPortAdvance.CHUNK_READY, out future_gusty1_chunk_ready);
            int action_id_gusty1_chunk_ready = future_gusty1_chunk_ready.GetHashCode();

            future_iteration.addAction(future_gusty1_chunk_ready);

            Console.WriteLine(this.ThisFacetInstance + "/" + this.Rank + ": WORKFLOW 5");

            IActionFuture future_data_terminate = null;

            Task_binding_data.invoke(ITaskPortData.TERMINATE, out future_data_terminate);
            future_iteration.addAction(future_data_terminate);
            int action_id_data_terminate = future_data_terminate.GetHashCode();

            Console.WriteLine(this.ThisFacetInstance + "/" + this.Rank + ": WORKFLOW 6-1");

            Task_binding_data.invoke(ITaskPortData.READ_SOURCE);

            Console.WriteLine(this.ThisFacetInstance + "/" + this.Rank + ": WORKFLOW 6-2");

            Task_binding_split_first.invoke(ITaskPortAdvance.READ_CHUNK);
            Task_binding_split_first.invoke(ITaskPortAdvance.PERFORM);

            Console.WriteLine(this.ThisFacetInstance + "/" + this.Rank + ": WORKFLOW 7");

            IList <Thread> bag_of_tasks = new List <Thread> ();


            bool terminate = false;

            do
            {
                Console.WriteLine(this.ThisFacetInstance + "/" + this.Rank + ": WORKFLOW 8 - LOOP");

                IActionFuture action = future_iteration.waitAny();

                int action_id = action.GetHashCode();
                if (action_id == action_id_split_first_chunk_ready)
                {
                    Thread t1 = new Thread((ThreadStart) delegate()
                    {
                        Console.WriteLine("INVOKE GUSTY0 READ_CHUNK - BEFORE");
                        Task_gusty0.invoke(ITaskPortAdvance.READ_CHUNK);
                        Console.WriteLine("INVOKE GUSTY0 READ_CHUNK - AFTER");
                        IActionFuture future_gusty0_perform = null;
                        Thread thread_gusty0_perform        = Task_gusty0.invoke(ITaskPortAdvance.PERFORM, gusty0_perform, out future_gusty0_perform);

                        Console.WriteLine("END INVOKE SPLITTER CHUNK_READY");
                    });

                    bag_of_tasks.Add(t1);
                    t1.Start();

                    Thread t2 = new Thread((ThreadStart) delegate()
                    {
                        Console.WriteLine("INVOKE SPLITTER READ_CHUNK");
                        Task_binding_split_first.invoke(ITaskPortAdvance.READ_CHUNK);
                        Console.WriteLine("INVOKE SPLITTER PERFORM");
                        Task_binding_split_first.invoke(ITaskPortAdvance.PERFORM);
                        Console.WriteLine("INVOKE SPLITTER READ_CHUNK/PERFORM - AFTER");
                        IActionFuture future_split_chunk_ready_ = null;
                        Task_binding_split_first.invoke(ITaskPortAdvance.CHUNK_READY, out future_split_chunk_ready_);
                        action_id_split_first_chunk_ready = future_split_chunk_ready_.GetHashCode();
                        future_iteration.addAction(future_split_chunk_ready_);
                    });

                    Console.WriteLine("THREAD LAUNCHED 1");

                    bag_of_tasks.Add(t2);
                    t2.Start();
                }
                else if (action_id == action_id_gusty0_chunk_ready)
                {
                    Task_gusty0.invoke(ITaskPortAdvance.CHUNK_READY, out future_gusty0_chunk_ready);
                    action_id_gusty0_chunk_ready = future_gusty0_chunk_ready.GetHashCode();
                    future_iteration.addAction(future_gusty0_chunk_ready);

                    Thread t = new Thread((ThreadStart) delegate()
                    {
                        Console.WriteLine("INVOKE STEP1 READ_CHUNK - BEFORE");                                   // 110 executados (o 48 completou nos pares, mas não progrediu aqui (????), motivo do erro.
                        Task_binding_step1.invoke(ITaskPortAdvance.READ_CHUNK);                                  //
                        Console.WriteLine("INVOKE STEP1 READ_CHUNK - AFTER");                                    // 47 completados
                        IActionFuture future_step1_perform = null;
                        Thread thread_step1_perform        = Task_binding_step1.invoke(ITaskPortAdvance.PERFORM, step1_perform, out future_step1_perform);

                        Console.WriteLine("END INVOKE GUSTY0 CHUNK_READY");
                    });
                    t.Start();
                    bag_of_tasks.Add(t);
                    Console.WriteLine("THREAD LAUNCHED 2");
                }
                else if (action_id == action_id_step1_chunk_ready)
                {
                    Task_binding_step1.invoke(ITaskPortAdvance.CHUNK_READY, out future_step1_chunk_ready);
                    action_id_step1_chunk_ready = future_step1_chunk_ready.GetHashCode();
                    future_iteration.addAction(future_step1_chunk_ready);

                    Thread t = new Thread((ThreadStart) delegate()
                    {
                        Console.WriteLine("INVOKE GUSTY1 READ_CHUNK - BEFORE");
                        Task_gusty1.invoke(ITaskPortAdvance.READ_CHUNK);                                  // ****
                        Console.WriteLine("INVOKE GUSTY1 READ_CHUNK - AFTER");
                        IActionFuture future_gusty1_perform = null;
                        Thread thread_gusty1_perform        = Task_gusty1.invoke(ITaskPortAdvance.PERFORM, gusty1_perform, out future_gusty1_perform);

                        Console.WriteLine("END INVOKE STEP1 CHUNK_READY");
                    });
                    t.Start();
                    bag_of_tasks.Add(t);
                    Console.WriteLine("THREAD LAUNCHED 3");
                }
                else if (action_id == action_id_gusty1_chunk_ready)
                {
                    Task_gusty1.invoke(ITaskPortAdvance.CHUNK_READY, out future_gusty1_chunk_ready);
                    action_id_gusty1_chunk_ready = future_gusty1_chunk_ready.GetHashCode();
                    future_iteration.addAction(future_gusty1_chunk_ready);

                    Thread t = new Thread((ThreadStart) delegate()
                    {
                        Console.WriteLine("INVOKE SPLITTER NEXT READ_CHUNK - BEFORE");
                        Task_binding_split_next.invoke(ITaskPortAdvance.READ_CHUNK);                                   // ****
                        Console.WriteLine("INVOKE SPLITTER NEXT READ_CHUNK - AFTER");
                        IActionFuture future_split_perform = null;
                        Thread thread_split_perform        = Task_binding_split_next.invoke(ITaskPortAdvance.PERFORM, split_perform, out future_split_perform);

                        Console.WriteLine("END INVOKE GUSTY1 CHUNK_READY");
                    });
                    t.Start();
                    bag_of_tasks.Add(t);
                    Console.WriteLine("THREAD LAUNCHED 4");
                }
                else if (action_id == action_id_split_next_chunk_ready)
                {
                    Thread t1 = new Thread((ThreadStart) delegate()
                    {
                        Console.WriteLine("INVOKE GUSTY0 READ_CHUNK NEXT - BEFORE");
                        Task_gusty0.invoke(ITaskPortAdvance.READ_CHUNK);                                    //
                        Console.WriteLine("INVOKE GUSTY0 READ_CHUNK NEXT - AFTER");
                        IActionFuture future_gusty0_perform = null;
                        Thread thread_gusty0_perform        = Task_gusty0.invoke(ITaskPortAdvance.PERFORM, gusty0_perform, out future_gusty0_perform);

                        Console.WriteLine("END INVOKE SPLIT NEXT CHUNK_READY");
                    });

                    bag_of_tasks.Add(t1);
                    t1.Start();

                    Thread t2 = new Thread((ThreadStart) delegate()
                    {
                        Console.WriteLine("INVOKE SPLITTER NEXT READ_CHUNK");
                        Task_binding_split_next.invoke(ITaskPortAdvance.READ_CHUNK);
                        Console.WriteLine("INVOKE SPLITTER NEXT PERFORM");
                        Task_binding_split_next.invoke(ITaskPortAdvance.PERFORM);
                        Console.WriteLine("INVOKE SPLITTER NEXT READ_CHUNK/PERFORM - AFTER");

                        IActionFuture future_split_next_chunk_ready_ = null;
                        Task_binding_split_next.invoke(ITaskPortAdvance.CHUNK_READY, out future_split_next_chunk_ready_);
                        action_id_split_next_chunk_ready = future_split_next_chunk_ready_.GetHashCode();
                        future_iteration.addAction(future_split_next_chunk_ready_);
                    });

                    Console.WriteLine("THREAD LAUNCHED 1");

                    bag_of_tasks.Add(t2);
                    t2.Start();

                    Console.WriteLine("THREAD LAUNCHED 5");
                }
                else if (action_id == action_id_data_terminate)
                {
                    Thread t = new Thread((ThreadStart) delegate()
                    {
                        Console.WriteLine("INVOKE DATA WRITE_SINK - BEFORE");
                        Task_binding_data.invoke(ITaskPortData.WRITE_SINK);
                        Console.WriteLine("INVOKE DATA WRITE_SINK - AFTER");
                        terminate = true;
                    });
                    t.Start();
                    bag_of_tasks.Add(t);
                    Console.WriteLine("THREAD LAUNCHED 6");
                }
                else
                {
                    Console.WriteLine("UNEXPECTED ERROR: ACTION FUTURE NOT RECOGNIZED ! ");
                }
            } while (!terminate);

            Console.WriteLine("WORKFLOW FINISHED ! ");

            foreach (Thread t in bag_of_tasks)
            {
                t.Join();
            }
        }
        //CONFIG
        public void readSource()
        {
            Console.WriteLine(this.GlobalRank + ": STARTING SPLITTER READSOURCE...1");
            output_instance_gifs = (IIteratorInstance <IKVPair <IInteger, IIterator <GIF> > >)Output_gifs.Instance;
            Feed_graph.Server    = output_instance_gifs;
            Console.WriteLine(this.GlobalRank + ": STARTING SPLITTER READSOURCE...2");

            // RECEIVE PAIR FROM THE SOURCE (1st iteration)
            Tuple <int, int> unit_ref_source = new Tuple <int, int> (this.FacetIndexes [FACET_SOURCE] [0], 0);

            //	Thread[] threads_receive = new Thread[senders_size];

            //	for (int i = 0; i < senders_size; i++)
            //	{
            //		threads_receive [i] = new Thread ((ParameterizedThreadStart)delegate(object unit_ref_obj) {
            //			Tuple<int,int> unit_ref_i = (Tuple<int,int>)unit_ref_obj;
            //			receive_pairs_iteration (unit_ref_i);
            //		});
            //	}

            // TODO: READ_SOURCE é necessário ? Não no map feeder. Tirar fatia de Task_binding data ...

            Task_binding_data.TraceFlag = true;
            Task_binding_data.invoke(ITaskPortData.READ_SOURCE);
            // Do nothing ...


            IList <IKVPairInstance <IInteger, GIF> > buffer;
            object buffer_obj;

            CompletedStatus status;


            do
            {
                IActionFuture sync_perform;

                Console.WriteLine(this.Rank + ": SPLITTER MAP FEEDER - BEFORE READ_CHUNK");

                Task_binding_split_first.invoke(ITaskPortAdvance.READ_CHUNK);                   //****
                Task_binding_split_first.invoke(ITaskPortAdvance.PERFORM, out sync_perform);

                IDictionary <object, IIteratorInstance <GIF> > kv_cache = new Dictionary <object, IIteratorInstance <GIF> > ();

                Console.WriteLine(this.Rank + ": SPLITTER MAP FEEDER !!! PERFORM OK !");

                Split_channel.Receive(unit_ref_source, MPI.Communicator.anyTag, out buffer, out status);

                Console.WriteLine(this.Rank + ": CHUNK PAIRS RECEIVED !!! from source buffer.Count=" + buffer.Count);

                //foreach (IKVPairInstance<IInteger,GIF> kv in buffer)
                //	output_instance_gif.put (kv);

                foreach (IKVPairInstance <IInteger, GIF> kv in buffer)
                {
                    IIteratorInstance <GIF> iterator = null;
                    if (!kv_cache.ContainsKey(kv.Key))
                    {
                        iterator = Value_factory_gif.newIteratorInstance();
                        kv_cache.Add(kv.Key, iterator);
                        IKVPairInstance <IInteger, IIterator <GIF> > item = (IKVPairInstance <IInteger, IIterator <GIF> >)Output_gifs.createItem();
                        item.Key   = kv.Key;
                        item.Value = iterator;
                        output_instance_gifs.put(item);
                    }
                    else
                    {
                        kv_cache.TryGetValue(kv.Key, out iterator);
                    }

                    iterator.put(kv.Value);
                }

                output_instance_gifs.finish();
                foreach (IIteratorInstance <IValue> iterator in kv_cache.Values)
                {
                    iterator.finish();
                }

                sync_perform.wait();

                // CHUNK_READY
                Console.WriteLine(this.Rank + ": SPLITTER MAP FEEDER 1");

                Task_binding_split_first.invoke(ITaskPortAdvance.CHUNK_READY);

                Console.WriteLine(this.Rank + ": SPLITTER MAP FEEDER 2");
            } while (status.Tag != TAG_SPLIT_END_CHUNK);

            output_instance_gifs.finish();

            Console.WriteLine(this.Rank + ": FINISH READING CHUNKS OF SOURCE");
        }
        public override void main()
        {
            Console.WriteLine(this.Rank + ": SPLITTER 1 ");

            IPortTypeIterator input_instance = (IPortTypeIterator)Source.Client;

            // TODO: será que READ_SOURCE é necessária ???
            Task_binding_data.TraceFlag = true;
            Task_binding_data.invoke(ITaskPortData.READ_SOURCE);

            // CALCULATE SubGraph TARGET
            int nfr    = this.FacetMultiplicity [FACET_REDUCE];
            int r_size = 0;

            foreach (int i in this.FacetIndexes[FACET_REDUCE])
            {
                r_size += this.UnitSizeInFacet [i] ["gusty_collector"];
            }
            Console.WriteLine(this.Rank + ": SPLITTER 2 ");

            Source.startReadSource(r_size);              // subgrafos divididos em GIF, com destino final nos r_size redutores

            Console.WriteLine(this.Rank + ": SPLITTER 3 ");

            object bin_object          = null;
            bool   set_table_partition = true;

            // CALCULATE TARGETs
            IDictionary <int, Tuple <int, int> > unit_ref = new Dictionary <int, Tuple <int, int> > ();
            int nf     = this.FacetMultiplicity [FACET_MAP];
            int m_size = 0;

            foreach (int i in this.FacetIndexes[FACET_MAP])
            {
                int nr0 = m_size;
                m_size += this.UnitSizeInFacet [i] ["gusty_feeder"];
                for (int k = 0, j = nr0; j < m_size; k++, j++)
                {
                    unit_ref [j] = new Tuple <int, int> (i /*, 0 INDEX OF gusty_feeder */, k);
                }
            }

            Console.WriteLine(this.Rank + ": SPLITTER 4 ");

            Task_binding_split_first.TraceFlag = true;
            Split_channel.TraceFlag            = true;

            Thread t_output = new Thread(new ThreadStart(delegate
            {
                Task_binding_data.invoke(ITaskPortData.TERMINATE);
                Task_binding_data.invoke(ITaskPortData.WRITE_SINK);
            }));

            t_output.Start();

            Console.WriteLine(this.Rank + ": SPLITTER 5 ");

            bool end_iteration = false;

            while (!end_iteration)             // take next chunk
            {
                IActionFuture sync_perform;

                Console.WriteLine(this.Rank + ": SPLITTER READ SOURCE - BEFORE READ_CHUNK " + m_size);

                /* All the pairs will be read from the source in a single chunk */

                Task_binding_split_first.invoke(ITaskPortAdvance.READ_CHUNK);                  //****
                Task_binding_split_first.invoke(ITaskPortAdvance.PERFORM, out sync_perform);

                IList <IKVPairInstance <IInteger, GIF> >[] buffer = new IList <IKVPairInstance <IInteger, GIF> > [m_size];
                for (int i = 0; i < m_size; i++)
                {
                    buffer [i] = new List <IKVPairInstance <IInteger, GIF> > ();
                }

                Console.WriteLine(this.Rank + ": BEGIN READING CHUNKS and distributing to MAPPERS m_size=" + m_size);

                if (!input_instance.has_next())
                {
                    end_iteration = true;
                }

                Bin_function_gif.NumberOfPartitions = m_size;
                while (input_instance.fetch_next(out bin_object))
                {
                    IKVPairInstance <IInteger, GIF> item = (IKVPairInstance <IInteger, GIF>)bin_object;
                    this.Input_key_gif.Instance = item.Value;                    //item.Key;
                    Bin_function_gif.go();
                    int index = ((IIntegerInstance)this.Output_key_gif.Instance).Value;
                    buffer [index].Add(item);
                }

                Console.WriteLine(this.Rank + ": END READING CHUNKS and distributing to MAPPERS");
                for (int i = 0; i < m_size; i++)
                {
                    Console.WriteLine("buffer[" + i + "].Count = " + buffer [i].Count);
                }

                Console.WriteLine(this.Rank + ": BEGIN SENDING CHUNKS to the MAPPERS ");
                // PERFORM
                for (int i = 0; i < m_size; i++)
                {
                    Split_channel.Send(buffer [i], unit_ref [i], end_iteration ? TAG_SPLIT_END_CHUNK : TAG_SPLIT_NEW_CHUNK);
                }

                sync_perform.wait();

                Console.WriteLine(this.Rank + ": END SENDING CHUNKS to the MAPPERS ");

                Task_binding_split_first.invoke(ITaskPortAdvance.CHUNK_READY);
            }

            Console.WriteLine(this.Rank + ": FINISH SPLITTER READ SOURCE ");

            t_output.Join();

            Console.WriteLine(this.Rank + ": FINISH SPLITTER READ SOURCE - INVOKE TERMINATE");
        }