Index: XIOS/trunk/src/context_server.cpp
===================================================================
--- XIOS/trunk/src/context_server.cpp	(revision 491)
+++ XIOS/trunk/src/context_server.cpp	(revision 492)
@@ -14,4 +14,7 @@
 #include "timer.hpp"
 #include "cxios.hpp"
+#include "event_scheduler.hpp"
+#include "server.hpp"
+#include <boost/functional/hash.hpp>
 
 
@@ -32,5 +35,10 @@
     else  MPI_Comm_size(interComm,&commSize) ;
     currentTimeLine=0 ;
+    scheduled=false ;
     finished=false ;
+    
+    boost::hash<string> hashString ;
+    hashId=hashString(context->getId()) ;
+
   }
   void CContextServer::setPendingEvent(void)
@@ -150,6 +158,14 @@
     {
       event=it->second ;
+      
       if (event->isFull())
       {
+        if (!scheduled && !CXios::isServer)
+        {
+          CServer::eventScheduler->registerEvent(currentTimeLine,hashId) ;  
+          scheduled=true ;
+        }
+        else if (CXios::isServer || CServer::eventScheduler->queryEvent(currentTimeLine,hashId) ) 
+        {
          CTimer::get("Process events").resume() ;
          dispatchEvent(*event) ;
@@ -159,7 +175,9 @@
          events.erase(it) ;
          currentTimeLine++ ;
-       }
-     }
-   }
+         scheduled = false ;
+        }
+      }
+    }
+  }
 
   CContextServer::~CContextServer()
Index: XIOS/trunk/src/context_server.hpp
===================================================================
--- XIOS/trunk/src/context_server.hpp	(revision 491)
+++ XIOS/trunk/src/context_server.hpp	(revision 492)
@@ -41,4 +41,6 @@
     bool finished ;
     bool pendingEvent ;
+    bool scheduled  ;    /*!< event of current timeline is alreading scheduled ? */
+    size_t hashId ;
     ~CContextServer() ;    
   } ;
Index: XIOS/trunk/src/event_scheduler.cpp
===================================================================
--- XIOS/trunk/src/event_scheduler.cpp	(revision 492)
+++ XIOS/trunk/src/event_scheduler.cpp	(revision 492)
@@ -0,0 +1,256 @@
+#include "event_scheduler.hpp"
+#include "xmlioserver_spl.hpp"
+#include "mpi.hpp"
+
+namespace xios
+{
+ 
+ 
+  CEventScheduler::CEventScheduler(const MPI_Comm& comm) 
+  {
+    MPI_Comm_dup(comm, &communicator) ;
+    MPI_Comm_size(communicator,&mpiSize) ;
+    MPI_Comm_rank(communicator,&mpiRank);
+
+
+    int maxChild=1 ;
+
+    int m ;
+    do
+    {
+      m=1 ;
+      maxChild=maxChild+1 ;
+      for(int i=0;i<maxChild;i++) m=m*maxChild ;
+     } while(m<mpiSize) ;
+    
+    
+    int maxLevel=0 ;
+    for(int size=1; size<=mpiSize; size*=maxChild) maxLevel++ ; 
+
+    int begin, end, nb ;
+    int pos, n ;
+ 
+    parent=vector<int>(maxLevel+1) ;
+    child=vector<vector<int> >(maxLevel+1,vector<int>(maxChild)) ;
+    nbChild=vector<int> (maxLevel+1) ;
+   
+    level=0 ;
+    begin=0 ;
+    end=mpiSize-1 ;     
+    nb=end-begin+1 ;
+     
+    do
+    {
+      n=0 ;
+      pos=begin ;
+      nbChild[level]=0 ;
+      parent[level+1]=begin ;
+      for(int i=0;i<maxChild && i<nb ;i++)
+      {
+        if (i<nb%maxChild) n = nb/maxChild + 1 ;
+        else n = nb/maxChild ;
+      
+        if (mpiRank>=pos && mpiRank<pos+n)
+        {
+          begin=pos ;
+          end=pos+n-1 ;
+        }
+        child[level][i]=pos ;
+        pos=pos+n ;
+        nbChild[level]++ ;
+      } 
+      nb=end-begin+1 ;
+      level=level+1 ;
+    } while (nb>1) ;
+
+    
+  }
+
+  CEventScheduler::~CEventScheduler()
+  {
+
+  } 
+
+  void CEventScheduler::registerEvent(const size_t timeLine, const size_t contextHashId)
+  {
+    registerEvent(timeLine, contextHashId, level) ;
+  }
+  
+  void CEventScheduler::registerEvent(const size_t timeLine, const size_t contextHashId, const size_t lev)
+  {
+       
+    SPendingRequest* sentRequest=new SPendingRequest ;
+    sentRequest->buffer[0]=timeLine ;
+    sentRequest->buffer[1]=contextHashId ;
+    sentRequest->buffer[2]=lev-1 ;
+
+    pendingSentParentRequest.push(sentRequest) ;
+    MPI_Isend(sentRequest->buffer,3, MPI_UNSIGNED_LONG, parent[lev], 0, communicator, &sentRequest->request) ;
+  } 
+
+  bool CEventScheduler::queryEvent(const size_t timeLine, const size_t contextHashId)
+  {
+
+    if (! eventStack.empty() && eventStack.front().first==timeLine && eventStack.front().second==contextHashId)
+    {
+      eventStack.pop() ;
+      return true ;
+    }
+    else return false ; 
+  } 
+  
+  void CEventScheduler::checkEvent(void)
+  {
+    checkChildRequest() ;
+    checkParentRequest() ;
+    
+  }
+  
+  
+  
+  void CEventScheduler::checkParentRequest(void)
+  {
+    int completed ;
+    MPI_Status status ;
+    int received ;
+    SPendingRequest* recvRequest ;
+    completed=true ;
+    
+    // check sent request to parent
+    while (! pendingSentParentRequest.empty() && completed)
+    {
+      MPI_Test( & pendingSentParentRequest.front()->request, &completed, &status) ;
+      if (completed) 
+      {
+        delete pendingSentParentRequest.front() ;
+        pendingSentParentRequest.pop() ;
+      }
+    }
+    
+    // probe if a message is coming from parent
+    received=true ;
+    while(received)
+    {
+      MPI_Iprobe(MPI_ANY_SOURCE,1,communicator,&received, &status) ;
+      if (received)
+      {
+        recvRequest=new SPendingRequest ;
+        MPI_Irecv(recvRequest->buffer, 3, MPI_UNSIGNED_LONG, MPI_ANY_SOURCE, 1, communicator, &(recvRequest->request)) ;
+        pendingRecvParentRequest.push(recvRequest) ;
+      }
+    }
+    
+     // check sent request from parent
+    completed=true ;
+    while (! pendingRecvParentRequest.empty() && completed)
+    {
+      recvRequest=pendingRecvParentRequest.front() ;
+      MPI_Test( &(recvRequest->request), &completed, &status) ;
+      if (completed) 
+      {
+        size_t timeLine=recvRequest->buffer[0] ;
+        size_t hashId=recvRequest->buffer[1] ;
+        size_t lev=recvRequest->buffer[2] ;
+        delete recvRequest ;
+        pendingRecvParentRequest.pop() ;       
+ 
+        if (lev==level) eventStack.push(pair<size_t,size_t>(timeLine,hashId)) ;
+        else  bcastEvent(timeLine, hashId, lev) ;
+      }
+    }   
+    
+  }
+
+  void CEventScheduler::checkChildRequest(void)
+  {
+// function call only by parent mpi process
+
+    MPI_Status status ; 
+    int received ;
+    received=true ;
+    SPendingRequest* recvRequest ;
+    
+    // check for posted requests and make the corresponding receive
+    while(received)
+    {
+      MPI_Iprobe(MPI_ANY_SOURCE,0,communicator,&received, &status) ;
+      if (received)
+      {
+        recvRequest=new SPendingRequest ;
+        MPI_Irecv(recvRequest->buffer, 3, MPI_UNSIGNED_LONG, MPI_ANY_SOURCE, 0, communicator, &recvRequest->request) ;
+        pendingRecvChildRequest.push_back(recvRequest) ;
+      }
+    }
+    
+    // check if receive request is achieved
+    
+    for(list<SPendingRequest*>::iterator it=pendingRecvChildRequest.begin(); it!=pendingRecvChildRequest.end() ; )
+    {
+      MPI_Test(&((*it)->request),&received,&status) ;
+      if (received)
+      {
+        size_t timeLine=(*it)->buffer[0] ;
+        size_t hashId=(*it)->buffer[1] ;
+        size_t lev=(*it)->buffer[2] ;
+        
+        SEvent event={timeLine,hashId,lev} ;
+        delete *it ; // free mem
+        it=pendingRecvChildRequest.erase(it) ; // get out of the list
+        
+        map< SEvent,int>::iterator itEvent=recvEvent.find(event) ;
+        if (itEvent==recvEvent.end()) 
+        {
+          itEvent=(recvEvent.insert(pair< SEvent ,int > (event,1))).first ;
+ 
+        }
+        else (itEvent->second)++ ;
+        if (itEvent->second==nbChild[lev])
+        {
+          if (lev==0)
+          {
+            bcastEvent(timeLine,hashId,lev) ;
+            recvEvent.erase(itEvent) ;
+          }
+          else
+          {
+            registerEvent( timeLine,hashId,lev) ;
+          }
+        }
+      }
+      else ++it ;
+    }
+    
+    // check if bcast request is achieved
+
+    for(list<SPendingRequest*>::iterator it=pendingSentChildRequest.begin(); it!=pendingSentChildRequest.end() ; )
+    {
+      MPI_Test(&(*it)->request,&received,&status) ;
+      if (received)
+      {
+        delete *it ;    // free memory
+        it = pendingSentChildRequest.erase(it) ;          // get out of the list
+
+      }
+      else ++it ;
+        
+    }
+  }
+  
+  void CEventScheduler::bcastEvent(const size_t timeLine, const size_t contextHashId, const size_t lev)
+  {
+    SPendingRequest* sentRequest ;
+     
+    
+    for(int i=0; i<nbChild[lev];i++)
+    {
+      sentRequest=new SPendingRequest ;
+      sentRequest->buffer[0]=timeLine ;
+      sentRequest->buffer[1]=contextHashId ;
+      sentRequest->buffer[2]=lev+1 ;
+      MPI_Isend(sentRequest->buffer,3, MPI_UNSIGNED_LONG, child[lev][i], 1, communicator, & sentRequest->request) ;
+      pendingSentChildRequest.push_back(sentRequest) ;
+    }
+  }
+   
+
+}
Index: XIOS/trunk/src/event_scheduler.hpp
===================================================================
--- XIOS/trunk/src/event_scheduler.hpp	(revision 492)
+++ XIOS/trunk/src/event_scheduler.hpp	(revision 492)
@@ -0,0 +1,176 @@
+#ifndef __EVENT_SCHEDULER_HPP__
+#define __EVENT_SCHEDULER_HPP__
+
+#include "xmlioserver_spl.hpp"
+#include "mpi.hpp"
+
+namespace xios
+{
+
+    //!  Event scheduling class. An instance of this class is used to order the event providing from different context to avoid dead lock.
+    /*!
+     *   Event are ordered in a same context using the timeLine id, so each server will process the same event. But between different
+     *   context, events are not scheduled and servers may choose to process different events and deadlock or MPI crash may occurs if
+     *   collective MPI communication are involved by the events. 
+     *   This class solve the problem by scheduling the event and choose which event must be process by each server to insure correct
+     *   synchronisation. Information is send by asynchronous MPI communication to the root process that order the different events
+     *   (First In First Out) and brodcast the information to the other servers. To avoid to much incoming communication for the root
+     *   process, and hierachical tree is used for communicating from a limited number of child processes to the parent.  
+     */
+    
+    class CEventScheduler
+    {
+       public:
+       //!  Constructor
+       /*! A new communicator is created by duplicate comm. The communicating tree hierarchy is created.
+        *  @param[in] comm : MPI communicator du duplicate for internal use
+        */
+       CEventScheduler(const MPI_Comm& comm) ;
+
+
+       //! Destructor
+       ~CEventScheduler() ;
+
+
+
+       //! public interface for registring an event from the server
+       /*!
+        *  @param[in] timeLine : Time line id of the event
+        *  @param[in] contextHashId : Hashed id of the context
+        */
+       void registerEvent(const size_t timeLine, const size_t contextHashId) ;
+
+
+
+       //! public interface for query if the event defined by timeLine and hashId is sheduled next
+       /*!
+        *  @param[in] timeLine : Time line id of the event
+        *  @param[in] contextHasId : Hashed id of the context
+        *  @return  : boolean value, true is the event is scheduled next
+        *
+        *  If the event is scheduled next, it is remove from the `eventStack` queue list  
+        */    
+       bool queryEvent(const size_t timeLine, const size_t contextHashId) ;
+
+
+       //! Public interface to give the hand to the instance to check pending or incoming message.
+       /*!
+        * Must be called periodicaly. Call `checkParentRequest` and `checkChildRequest` private method.
+        */
+       void checkEvent(void) ;
+
+       private:
+
+
+       //! Send an event to the parent of level `lev+1`
+       /*!
+        *  @param[in] timeLine : Time line id of the event
+        *  @param[in] contextHasId : Hashed id of the context
+        *  @param[in] lev : actual level of the child in the hierarchy
+        *  The event is sent by an asynchrounous MPI_ISend
+        */
+       void registerEvent(const size_t timeLine, const size_t contextHashId, const size_t lev) ;
+
+
+
+       //! Children side. Check potential incoming message and if pending request are completed 
+       /*!
+        *  - Check by `MPI_Test` if pending request sent to parents are complete.
+        *  - Probe incoming message from parent by using `MPI_Probe`. If yes, post an asynchronous reception by `MPI_IRecv`
+        *  - Check by `MPI_Test` if pending received requests are complete. if yes :
+        *    + Broadcast the event to the childrens if is also a parent
+        *    + Otherwise : push the incomming event in the `eventStack` queue.
+        */
+       void checkParentRequest(void) ;
+
+
+
+       //! Parent side. Check potential incoming message and if pending request are completed
+       /*!
+        *  - Probe incoming message from chidren by using `MPI_Probe`. If yes, post an asynchronous reception by `MPI_IRecv`.
+        *  - Check pending received event request from children using `MPI_Probe`. If and event is received, it is incerted in the
+        *    map `recvEvent` which is increased by 1. If the number of request received from children for this event is equal to the number
+        *    of children then :
+        *    + if the event level is 0, bcast the event to the children.
+        *    + else send the event to the parent.
+        *  - Check pending sent event request to children using `MPI_TEST` and if complete release the corresponding buffer 
+        */
+       void checkChildRequest(void) ;
+
+
+
+       //! Parent side. Broadcast a received event from the parent to the children.
+       /*!
+        *  @param[in] timeLine : Time line id of the event
+        *  @param[in] contextHasId : Hashed id of the context
+        *  @param[in] lev : actual level of the child in the hierarchy
+        * Asynchronus MPI_ISend is used.
+        */
+       void bcastEvent(const size_t timeLine, const size_t contextHashId, const size_t lev) ;
+       
+
+
+
+       //! Structure defining an event, composed of the timeLine, the context hashId and the hierachical level of the communication.
+       struct SEvent
+       {
+         size_t timeLine ; /*!< Time line id of the event in the context */
+         size_t hashId ; /*!< hassh id of the context */
+         size_t level ;  /*!<hierarchical level of the communication*/
+
+         //! Definition of the == operator : needed to order the object in a map container
+         /*!
+            @param[in] e : object to compare with
+            @return : boolean result of the comparison
+         */
+         bool operator==(const SEvent& e) const
+         { 
+           if (timeLine == e.timeLine && hashId == e.hashId && level==e.level) return true ;
+           else return false ;
+         } ;
+        
+
+         //! Definition of the < operator : needed to order the object in a map container
+         /*!
+            @param[in] e : object to compare with
+            @return : boolean result of the comparison
+         */
+
+         bool operator<(const SEvent& e) const
+         { 
+           if (timeLine < e.timeLine) return true ;
+           else if (timeLine == e.timeLine && hashId < e.hashId) return true ;
+           else if (timeLine == e.timeLine && hashId == e.hashId && level<e.level) return true ;
+           else return false ;
+         } ;
+       } ;       
+        
+
+       //! Pending request struture. It keep send or receive buffer from asynchronous communication while the request is not complete.
+       struct SPendingRequest
+       {
+         size_t buffer[3] ;      /*!< communication buffer : timeLine, hashId, level */
+         MPI_Request request ;   /*!< pending MPI request */ 
+       } ;
+       
+       MPI_Comm communicator ;  /*!< Internal MPI communicator */ 
+       int mpiRank ;            /*!< Rank in the communicator */
+       int mpiSize ;            /*!< Size of the communicator */
+ 
+       queue< pair<size_t, size_t> > eventStack ;          
+       queue<SPendingRequest* > pendingSentParentRequest ;   /*!< Pending request sent to parent   */
+       queue<SPendingRequest*>  pendingRecvParentRequest ;   /*!< Pending request recv from parent */    
+       list<SPendingRequest* >  pendingRecvChildRequest ;    /*!< Pending request recv from child  */
+       list<SPendingRequest*>   pendingSentChildRequest ;    /*!< Pending request sent to child    */
+       map< SEvent, int > recvEvent ;                        /*!< list of event received from children. Contains the currnet number children that have already post the same event */
+       
+       
+       int level ;                   /*!< Number of hierachical level for communication */
+       vector<int> parent ;          /*!< Parent rank for each level */ 
+       vector<vector<int> >  child ; /*!< List of child rank for each level */
+       vector<int> nbChild ;         /*!< Number of child for each level */    
+
+    } ;
+}
+
+#endif
Index: XIOS/trunk/src/server.cpp
===================================================================
--- XIOS/trunk/src/server.cpp	(revision 491)
+++ XIOS/trunk/src/server.cpp	(revision 492)
@@ -12,4 +12,5 @@
 #include "tracer.hpp"
 #include "timer.hpp"
+#include "event_scheduler.hpp"
 
 namespace xios
@@ -23,4 +24,5 @@
     bool CServer::finished=false ;
     bool CServer::is_MPI_Initialized ;
+    CEventScheduler* CServer::eventScheduler ;
 
     void CServer::initialize(void)
@@ -86,4 +88,9 @@
            {
              clientLeader=it->second ;
+             int intraCommSize, intraCommRank ;
+             MPI_Comm_size(intraComm,&intraCommSize) ;
+             MPI_Comm_rank(intraComm,&intraCommRank) ;
+             cout<<"intercommCreate::server "<<rank<<" intraCommSize : "<<intraCommSize
+                 <<" intraCommRank :"<<intraCommRank<<"  clientLeader "<< clientLeader<<endl ;
 
              MPI_Intercomm_create(intraComm,0,CXios::globalComm,clientLeader,0,&newComm) ;
@@ -122,5 +129,5 @@
           interComm.push_back(newComm) ;
         }
-	oasis_enddef() ;
+	      oasis_enddef() ;
       }
 
@@ -129,6 +136,6 @@
       if (rank==0) isRoot=true;
       else isRoot=false;
-//      eventLoop() ;
-//      finalize() ;
+      
+      eventScheduler = new CEventScheduler(intraComm) ;
     }
 
@@ -136,4 +143,7 @@
     {
       CTimer::get("XIOS").suspend() ;
+      
+      delete eventScheduler ;
+      
       if (!is_MPI_Initialized)
       {
@@ -166,4 +176,5 @@
          contextEventLoop() ;
          if (finished && contextList.empty()) stop=true ;
+         if (! CXios::isServer) eventScheduler->checkEvent() ;
        }
        CTimer::get("XIOS server").suspend() ;
Index: XIOS/trunk/src/server.hpp
===================================================================
--- XIOS/trunk/src/server.hpp	(revision 491)
+++ XIOS/trunk/src/server.hpp	(revision 492)
@@ -5,4 +5,5 @@
 #include "context.hpp"
 #include "mpi.hpp"
+#include "event_scheduler.hpp"
 
 namespace xios
@@ -25,4 +26,5 @@
        static MPI_Comm intraComm ;
        static list<MPI_Comm> interComm ;
+       static CEventScheduler* eventScheduler ;
 
        struct contextMessage
Index: XIOS/trunk/src/xmlioserver_spl.hpp
===================================================================
--- XIOS/trunk/src/xmlioserver_spl.hpp	(revision 491)
+++ XIOS/trunk/src/xmlioserver_spl.hpp	(revision 492)
@@ -20,4 +20,5 @@
 #include <map>
 #include <deque>
+#include <queue>
 #include <valarray>
 // Flux.
