/*
    Copyright 2005-2010 Intel Corporation.  All Rights Reserved.

    This file is part of Threading Building Blocks.

    Threading Building Blocks is free software; you can redistribute it
    and/or modify it under the terms of the GNU General Public License
    version 2 as published by the Free Software Foundation.

    Threading Building Blocks 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 Threading Building Blocks; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

    As a special exception, you may use this file as part of a free software
    library without restriction.  Specifically, if other files instantiate
    templates or use macros or inline functions from this file, or you compile
    this file and link it with other files to produce an executable, this
    file does not by itself cause the resulting executable to be covered by
    the GNU General Public License.  This exception does not however
    invalidate any other reasons why the executable file might be covered by
    the GNU General Public License.
*/

#ifndef __TBB_task_group_H
#define __TBB_task_group_H

#include "task.h"
#include "tbb_exception.h"

namespace tbb {

namespace internal {
    template<typename F> class task_handle_task;
}

template<typename F>
class task_handle : internal::no_assign {
    template<typename _F> friend class internal::task_handle_task;

    static const intptr_t scheduled = 0x1;

    F my_func;
    intptr_t my_state;

    void mark_scheduled () {
        // The check here is intentionally lax to avoid the impact of interlocked operation
        if ( my_state & scheduled )
            internal::throw_exception( internal::eid_invalid_multiple_scheduling );
        my_state |= scheduled;
    }
public:
    task_handle( const F& f ) : my_func(f), my_state(0) {}

    void operator() () const { my_func(); }
};

enum task_group_status {
    not_complete,
    complete,
    canceled
};

namespace internal {

// Suppress gratuitous warnings from icc 11.0 when lambda expressions are used in instances of function_task.
//#pragma warning(disable: 588)

template<typename F>
class function_task : public task {
    F my_func;
    /*override*/ task* execute() {
        my_func();
        return NULL;
    }
public:
    function_task( const F& f ) : my_func(f) {}
};

template<typename F>
class task_handle_task : public task {
    task_handle<F>& my_handle;
    /*override*/ task* execute() {
        my_handle();
        return NULL;
    }
public:
    task_handle_task( task_handle<F>& h ) : my_handle(h) { h.mark_scheduled(); }
};

class task_group_base : internal::no_copy {
protected:
    empty_task* my_root;
    task_group_context my_context;

    task& owner () { return *my_root; }

    template<typename F>
    task_group_status internal_run_and_wait( F& f ) {
        __TBB_TRY {
            if ( !my_context.is_group_execution_cancelled() )
                f();
        } __TBB_CATCH( ... ) {
            my_context.register_pending_exception();
        }
        return wait();
    }

    template<typename F, typename Task>
    void internal_run( F& f ) {
        owner().spawn( *new( owner().allocate_additional_child_of(*my_root) ) Task(f) );
    }

public:
    task_group_base( uintptr_t traits = 0 )
        : my_context(task_group_context::bound, task_group_context::default_traits | traits)
    {
        my_root = new( task::allocate_root(my_context) ) empty_task;
        my_root->set_ref_count(1);
    }

    template<typename F>
    void run( task_handle<F>& h ) {
        internal_run< task_handle<F>, internal::task_handle_task<F> >( h );
    }

    task_group_status wait() {
        __TBB_TRY {
            my_root->wait_for_all();
        } __TBB_CATCH( ... ) {
            my_context.reset();
            __TBB_RETHROW();
        }
        if ( my_context.is_group_execution_cancelled() ) {
            my_context.reset();
            return canceled;
        }
        return complete;
    }

    bool is_canceling() {
        return my_context.is_group_execution_cancelled();
    }

    void cancel() {
        my_context.cancel_group_execution();
    }
}; // class task_group_base

} // namespace internal

class task_group : public internal::task_group_base {
public:
    task_group () : task_group_base( task_group_context::concurrent_wait ) {}

    ~task_group() __TBB_TRY {
        __TBB_ASSERT( my_root->ref_count() != 0, NULL );
        if( my_root->ref_count() > 1 )
            my_root->wait_for_all();
        owner().destroy(*my_root);
    }
#if TBB_USE_EXCEPTIONS
    catch (...) {
        owner().destroy(*my_root);
        throw;
    }
#endif /* TBB_USE_EXCEPTIONS */

#if __SUNPRO_CC
    template<typename F>
    void run( task_handle<F>& h ) {
        internal_run< task_handle<F>, internal::task_handle_task<F> >( h );
    }
#else
    using task_group_base::run;
#endif

    template<typename F>
    void run( const F& f ) {
        internal_run< const F, internal::function_task<F> >( f );
    }

    template<typename F>
    task_group_status run_and_wait( const F& f ) {
        return internal_run_and_wait<const F>( f );
    }

    template<typename F>
    task_group_status run_and_wait( task_handle<F>& h ) {
      return internal_run_and_wait< task_handle<F> >( h );
    }
}; // class task_group

class structured_task_group : public internal::task_group_base {
public:
    ~structured_task_group() {
        if( my_root->ref_count() > 1 ) {
            bool stack_unwinding_in_progress = std::uncaught_exception();
            // Always attempt to do proper cleanup to avoid inevitable memory corruption 
            // in case of missing wait (for the sake of better testability & debuggability)
            if ( !is_canceling() )
                cancel();
            my_root->wait_for_all();
            owner().destroy(*my_root);
            if ( !stack_unwinding_in_progress )
                internal::throw_exception( internal::eid_missing_wait );
        }
        else {
            if( my_root->ref_count() == 1 )
                my_root->set_ref_count(0);
            owner().destroy(*my_root);
        }
    }

    template<typename F>
    task_group_status run_and_wait ( task_handle<F>& h ) {
        return internal_run_and_wait< task_handle<F> >( h );
    }

    task_group_status wait() {
        task_group_status res = task_group_base::wait();
        my_root->set_ref_count(1);
        return res;
    }
}; // class structured_task_group

inline 
bool is_current_task_group_canceling() {
    return task::self().is_cancelled();
}

template<class F>
task_handle<F> make_task( const F& f ) {
    return task_handle<F>( f );
}

} // namespace tbb

#endif /* __TBB_task_group_H */
