// Collection of synchronisation states -*- c++ -*-

#ifndef SYNCSTATES_H_
# define SYNCSTATES_H_
# ifdef __GNUC__
#  pragma interface
# endif // __GNUC__

# include <map>
# include <set>

# include "BitBuffer.h"

/** @file SyncStates.h
 * Collection of synchronisation states for modular analysis
 */

/* Copyright © 2002-2003 Marko Mäkelä (msmakela@tcs.hut.fi).

   This file is part of MARIA, a reachability analyzer and model checker
   for high-level Petri nets.

   MARIA is free software; you can redistribute it and/or modify it
   under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2, or (at your option)
   any later version.

   MARIA 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.

   The GNU General Public License is often shipped with GNU software, and
   is generally kept in a file called COPYING or LICENSE.  If you do not
   have a copy of the license, write to the Free Software Foundation,
   59 Temple Place, Suite 330, Boston, MA 02111 USA. */

/** Collection of synchronisation states for modular analysis */
class SyncStates
{
public:
  /** Map of synchronisation labels to label numbers */
  typedef std::map<const class Transition*,unsigned> TransitionMap;
  /** Comparison operator for encoded states */
  struct ltstate
  {
    /** Less-than comparison
     * @param s1	first state to be compared
     * @param s2	second state to be compared
     * @return		true if s1 < s2
     */
    bool operator() (const word_t* s1,
		     const word_t* s2) const {
      return *s1 == *s2
	? memcmp (s1 + 1, s2 + 1, *s1 * sizeof *s1)
	: (*s1 < *s2);
    }
  };
  /** Set of encoded states */
  typedef std::set<word_t*,struct ltstate> StateSet;
# ifdef SYNC_CACHE
  /** Map from (child,state) pairs to basic indexes to state sets */
  typedef std::map<word_t*,unsigned,struct ltstate> StateMap;
# endif // SYNC_CACHE

  /** Constructor
   * @param net		the net whose children are being synchronised
   */
  SyncStates (const class Net& net);
private:
  /** Copy constructor */
  SyncStates (const class SyncStates& old);
  /** Assignment operator */
  class SyncStates& operator= (const class SyncStates& old);
public:
  /** Destructor */
  ~SyncStates ();

# ifdef SYNC_CACHE
  /** Look up the synchronisation states of a module at a specific state
   * @param module	the index of the module
   * @param buf		the encoded source state
   * @param size	length of the encoded state in words
   * @return		whether the state has been already explored
   */
  bool lookup (unsigned module,
	       const word_t* buf,
	       word_t size);
# else // SYNC_CACHE
  /** Clean up the set of synchronisation states and labels */
  void cleanup ();
# endif // SYNC_CACHE

  /** Add a synchronisation state
   * @param transition	the child transition
   * @param buf		the encoded source state
   * @param size	length of the encoded state in words
   */
  void add (const class Transition& transition,
	    const word_t* buf,
	    word_t size);

  /** Synchronise on a label
   * @param m		the source marking
   * @param transition	the synchronisation label
   * @param reporter	the interface for reporting successor states
   */
  void sync (const class GlobalMarking& m,
	     const class Transition& transition,
	     class StateReporter& reporter) const;
# ifdef EXPR_COMPILE
  /** Synchronise on a label
   * @param transition	the synchronisation label
   * @param reporter	the interface for reporting successor states
   * @param srcs	encoded inflated states (for restoring the state)
   */
  void sync (const class Transition& transition,
	     class StateReporter& reporter,
	     word_t** srcs) const;
# endif // EXPR_COMPILE

private:
  /** Number of modules */
  const unsigned myNumModules;
  /** Map from synchronisation labels to index numbers */
  const TransitionMap myTransitionMap;
# ifdef SYNC_CACHE
  /** Maps from states to myStateSet[] base indexes, indexed by module */
  StateMap* myStateMap;
  /** Sets of synchronisation states indexed by (src,child)+label numbers */
  StateSet** myStateSet;
  /** myStateSet[] base indexes corresponding to the current (child,src) */
  unsigned* myStateIndex;
  /** Used number of entries in myStateSet */
  unsigned myStateUsed;
  /** Allocated number of entries for myStateSet */
  unsigned myStateAlloc;
# else // SYNC_CACHE
  /** Sets of synchronisation states indexed by module+myNumModules*label */
  StateSet** const myStateSet;
  /** Enabled labels */
  bool* const myEnabled;
# endif // SYNC_CACHE
# ifdef ADD_CACHE
  /** Synchronisation states that have already been processed */
  mutable class FullSet* mySync;
# endif // ADD_CACHE
};

#endif // SYNCSTATES_H_
