<commit_before>/////////////////////////////////////////////////////////////////////////
// $Id: ioapic.cc,v 1.32 2006/06/05 05:39:21 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
//  Copyright (C) 2002  MandrakeSoft S.A.
//
//    MandrakeSoft S.A.
//    43, rue d'Aboukir
//    75002 Paris - France
//    http://www.linux-mandrake.com/
//    http://www.mandrakesoft.com/
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library 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
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA

#include "bochs.h"
#include "cpu/apic.h"
#include "iodev.h"

#if BX_SUPPORT_APIC

class bx_ioapic_c bx_ioapic;
#define LOG_THIS  bx_ioapic.

static bx_bool ioapic_read(unsigned long a20addr, unsigned long len, void *data, void *param)
{
  bx_ioapic.read(a20addr, data, len);
  return 1;
}

static bx_bool ioapic_write(unsigned long a20addr, unsigned long len, void *data, void *param)
{
  if (len != 4) {
    BX_PANIC (("I/O apic write with len=%d (should be 4)", len));
  }
  bx_ioapic.write(a20addr, (Bit32u*) data, len);
  return 1;
}

void bx_io_redirect_entry_t::sprintf_self(char *buf)
{
  sprintf(buf, "dest=%02x, masked=%d, trig_mode=%d, remote_irr=%d, polarity=%d, delivery_status=%d, dest_mode=%d, delivery_mode=%d, vector=%02x",
     (unsigned) destination(),
     (unsigned) is_masked(),
     (unsigned) trigger_mode(),
     (unsigned) remote_irr(),
     (unsigned) pin_polarity(),
     (unsigned) delivery_status(),
     (unsigned) destination_mode(),
     (unsigned) delivery_mode(),
     (unsigned) vector());
}

#if BX_SUPPORT_SAVE_RESTORE
void bx_io_redirect_entry_t::register_state(bx_param_c *parent)
{
  BXRS_HEX_PARAM_SIMPLE(parent, lo);
  BXRS_HEX_PARAM_SIMPLE(parent, hi);
}
#endif

#define BX_IOAPIC_BASE_ADDR (0xfec00000)

bx_ioapic_c::bx_ioapic_c()
  : bx_generic_apic_c(BX_IOAPIC_BASE_ADDR)
{
  put("IOAP");
  settype(IOAPICLOG);
}

bx_ioapic_c::~bx_ioapic_c() {}

#define BX_IOAPIC_DEFAULT_ID (BX_SMP_PROCESSORS)

void bx_ioapic_c::init(void)
{
  bx_generic_apic_c::init();
  BX_INFO(("initializing I/O APIC"));
  base_addr = BX_IOAPIC_BASE_ADDR;
  set_id(BX_IOAPIC_DEFAULT_ID);
  ioregsel = 0;
  DEV_register_memory_handlers(&bx_ioapic,
      ioapic_read, ioapic_write, base_addr, base_addr + 0xfff);
  // all interrupts masked
  for (int i=0; i<BX_IOAPIC_NUM_PINS; i++) {
    ioredtbl[i].set_lo_part(0x00010000);
    ioredtbl[i].set_hi_part(0x00000000);
  }
  intin = 0;
  irr = 0;
}

void bx_ioapic_c::read_aligned(bx_phy_address address, Bit32u *data)
{
  BX_DEBUG(("IOAPIC: read aligned addr=%08x", address));
  address &= 0xff;
  if (address == 0x00) {
    // select register
    *data = ioregsel;
    return;
  } else {
    if (address != 0x10)
      BX_PANIC(("IOAPIC: read from unsupported address"));
  }
  // only reached when reading data register
  switch (ioregsel) {
  case 0x00:  // APIC ID, note this is 4bits, the upper 4 are reserved
    *data = ((id & APIC_ID_MASK) << 24);
    return;
  case 0x01:  // version
    *data = BX_IOAPIC_VERSION_ID;
    return;
  case 0x02:
    BX_INFO(("IOAPIC: arbitration ID unsupported, returned 0"));
    *data = 0;
    return;
  default:
    int index = (ioregsel - 0x10) >> 1;
    if (index >= 0 && index < BX_IOAPIC_NUM_PINS) {
      bx_io_redirect_entry_t *entry = ioredtbl + index;
      *data = (ioregsel&1) ? entry->get_hi_part() : entry->get_lo_part();
      return;
    }
    BX_PANIC(("IOAPIC: IOREGSEL points to undefined register %02x", ioregsel));
  }
}

void bx_ioapic_c::write_aligned(bx_phy_address address, Bit32u *value)
{
  BX_DEBUG(("IOAPIC: write aligned addr=%08x, data=%08x", address, *value));
  address &= 0xff;
  if (address == 0x00)  {
    ioregsel = *value;
    return;
  } else {
    if (address != 0x10)
      BX_PANIC(("IOAPIC: write to unsupported address"));
  }
  // only reached when writing data register
  switch (ioregsel) {
    case 0x00: // set APIC ID
      {
	Bit8u newid = (*value >> 24) & APIC_ID_MASK;
	BX_INFO(("IOAPIC: setting id to 0x%x", newid));
	set_id (newid);
	return;
      }
    case 0x01: // version
    case 0x02: // arbitration id
      BX_INFO(("IOAPIC: could not write, IOREGSEL=0x%02x", ioregsel));
      return;
    default:
      int index = (ioregsel - 0x10) >> 1;
      if (index >= 0 && index < BX_IOAPIC_NUM_PINS) {
	bx_io_redirect_entry_t *entry = ioredtbl + index;
	if (ioregsel&1)
	  entry->set_hi_part(*value);
	else
	  entry->set_lo_part(*value);
	char buf[1024];
	entry->sprintf_self(buf);
	BX_DEBUG(("IOAPIC: now entry[%d] is %s", index, buf));
	service_ioapic();
	return;
      }
      BX_PANIC(("IOAPIC: IOREGSEL points to undefined register %02x", ioregsel));
  }
}

void bx_ioapic_c::set_irq_level(Bit8u int_in, bx_bool level)
{
  BX_DEBUG(("set_irq_level(): INTIN%d: level=%d", int_in, level));
  if (int_in < BX_IOAPIC_NUM_PINS) {
    Bit32u bit = 1<<int_in;
    if ((level<<int_in) != (intin & bit)) {
      bx_io_redirect_entry_t *entry = ioredtbl + int_in;
      if (entry->trigger_mode()) {
        // level triggered
        if (level) {
          intin |= bit;
          irr |= bit;
          service_ioapic();
        } else {
          intin &= ~bit;
          irr &= ~bit;
        }
      } else {
        // edge triggered
        if (level) {
          intin |= bit;
          irr |= bit;
          service_ioapic();
        } else {
          intin &= ~bit;
        }
      }
    }
  }
}

void bx_ioapic_c::receive_eoi(Bit8u vector)
{
  BX_DEBUG(("IOAPIC: received EOI for vector %d", vector));
}

void bx_ioapic_c::service_ioapic()
{
  static unsigned int stuck = 0;
  // look in IRR and deliver any interrupts that are not masked.
  BX_DEBUG(("IOAPIC: servicing"));
  for (unsigned bit=0; bit < BX_IOAPIC_NUM_PINS; bit++) {
    Bit32u mask = 1<<bit;
    if (irr & mask) {
      bx_io_redirect_entry_t *entry = ioredtbl + bit;
      if (! entry->is_masked()) {
        // clear irr bit and deliver
        if (entry->delivery_mode() == 7) {
          BX_PANIC(("ExtINT not implemented yet"));
        }
        bx_bool done = apic_bus_deliver_interrupt(entry->vector(), entry->destination(), entry->delivery_mode(), entry->destination_mode(), entry->pin_polarity(), entry->trigger_mode());
        if (done) {
          if (! entry->trigger_mode())
            irr &= ~mask;
          entry->clear_delivery_status();
          stuck = 0;
        } else {
          entry->set_delivery_status();
          stuck++;
          if (stuck > 5)
            BX_INFO(("vector %#x stuck?", entry->vector()));
        }
      }
      else {
        BX_DEBUG(("service_ioapic(): INTIN%d is masked", bit));
      }
    }
  }
}

#if BX_SUPPORT_SAVE_RESTORE
void bx_ioapic_c::register_state(void)
{
  bx_list_c *list = new bx_list_c(SIM->get_sr_root(), "ioapic", "IOAPIC State");
  BXRS_HEX_PARAM_SIMPLE(list, ioregsel);
  BXRS_HEX_PARAM_SIMPLE(list, intin);
  BXRS_HEX_PARAM_SIMPLE(list, irr);

  bx_list_c *table = new bx_list_c(list, "ioredtbl", BX_IOAPIC_NUM_PINS);
  for (unsigned i=0; i<BX_IOAPIC_NUM_PINS; i++) {
    char name[6];
    sprintf(name, "0x%02x", i);
    bx_list_c *entry = new bx_list_c(table, name, 2);
    ioredtbl[i].register_state(entry);
  }
}
#endif

#endif /* if BX_SUPPORT_APIC */
<commit_msg>- ExtINT implemented (some progress with FreeBSD 5.3 boot cd) - fixed a warning<commit_after>/////////////////////////////////////////////////////////////////////////
// $Id: ioapic.cc,v 1.33 2006/10/02 15:08:21 vruppert Exp $
/////////////////////////////////////////////////////////////////////////
//
//  Copyright (C) 2002  MandrakeSoft S.A.
//
//    MandrakeSoft S.A.
//    43, rue d'Aboukir
//    75002 Paris - France
//    http://www.linux-mandrake.com/
//    http://www.mandrakesoft.com/
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library 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
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA

#include "bochs.h"
#include "cpu/apic.h"
#include "iodev.h"

#if BX_SUPPORT_APIC

class bx_ioapic_c bx_ioapic;
#define LOG_THIS  bx_ioapic.

static bx_bool ioapic_read(unsigned long a20addr, unsigned long len, void *data, void *param)
{
  bx_ioapic.read(a20addr, data, len);
  return 1;
}

static bx_bool ioapic_write(unsigned long a20addr, unsigned long len, void *data, void *param)
{
  if (len != 4) {
    BX_PANIC (("I/O apic write with len=%ld (should be 4)", len));
  }
  bx_ioapic.write(a20addr, (Bit32u*) data, len);
  return 1;
}

void bx_io_redirect_entry_t::sprintf_self(char *buf)
{
  sprintf(buf, "dest=%02x, masked=%d, trig_mode=%d, remote_irr=%d, polarity=%d, delivery_status=%d, dest_mode=%d, delivery_mode=%d, vector=%02x",
     (unsigned) destination(),
     (unsigned) is_masked(),
     (unsigned) trigger_mode(),
     (unsigned) remote_irr(),
     (unsigned) pin_polarity(),
     (unsigned) delivery_status(),
     (unsigned) destination_mode(),
     (unsigned) delivery_mode(),
     (unsigned) vector());
}

#if BX_SUPPORT_SAVE_RESTORE
void bx_io_redirect_entry_t::register_state(bx_param_c *parent)
{
  BXRS_HEX_PARAM_SIMPLE(parent, lo);
  BXRS_HEX_PARAM_SIMPLE(parent, hi);
}
#endif

#define BX_IOAPIC_BASE_ADDR (0xfec00000)

bx_ioapic_c::bx_ioapic_c()
  : bx_generic_apic_c(BX_IOAPIC_BASE_ADDR)
{
  put("IOAP");
  settype(IOAPICLOG);
}

bx_ioapic_c::~bx_ioapic_c() {}

#define BX_IOAPIC_DEFAULT_ID (BX_SMP_PROCESSORS)

void bx_ioapic_c::init(void)
{
  bx_generic_apic_c::init();
  BX_INFO(("initializing I/O APIC"));
  base_addr = BX_IOAPIC_BASE_ADDR;
  set_id(BX_IOAPIC_DEFAULT_ID);
  ioregsel = 0;
  DEV_register_memory_handlers(&bx_ioapic,
      ioapic_read, ioapic_write, base_addr, base_addr + 0xfff);
  // all interrupts masked
  for (int i=0; i<BX_IOAPIC_NUM_PINS; i++) {
    ioredtbl[i].set_lo_part(0x00010000);
    ioredtbl[i].set_hi_part(0x00000000);
  }
  intin = 0;
  irr = 0;
}

void bx_ioapic_c::read_aligned(bx_phy_address address, Bit32u *data)
{
  BX_DEBUG(("IOAPIC: read aligned addr=%08x", address));
  address &= 0xff;
  if (address == 0x00) {
    // select register
    *data = ioregsel;
    return;
  } else {
    if (address != 0x10)
      BX_PANIC(("IOAPIC: read from unsupported address"));
  }
  // only reached when reading data register
  switch (ioregsel) {
  case 0x00:  // APIC ID, note this is 4bits, the upper 4 are reserved
    *data = ((id & APIC_ID_MASK) << 24);
    return;
  case 0x01:  // version
    *data = BX_IOAPIC_VERSION_ID;
    return;
  case 0x02:
    BX_INFO(("IOAPIC: arbitration ID unsupported, returned 0"));
    *data = 0;
    return;
  default:
    int index = (ioregsel - 0x10) >> 1;
    if (index >= 0 && index < BX_IOAPIC_NUM_PINS) {
      bx_io_redirect_entry_t *entry = ioredtbl + index;
      *data = (ioregsel&1) ? entry->get_hi_part() : entry->get_lo_part();
      return;
    }
    BX_PANIC(("IOAPIC: IOREGSEL points to undefined register %02x", ioregsel));
  }
}

void bx_ioapic_c::write_aligned(bx_phy_address address, Bit32u *value)
{
  BX_DEBUG(("IOAPIC: write aligned addr=%08x, data=%08x", address, *value));
  address &= 0xff;
  if (address == 0x00)  {
    ioregsel = *value;
    return;
  } else {
    if (address != 0x10)
      BX_PANIC(("IOAPIC: write to unsupported address"));
  }
  // only reached when writing data register
  switch (ioregsel) {
    case 0x00: // set APIC ID
      {
	Bit8u newid = (*value >> 24) & APIC_ID_MASK;
	BX_INFO(("IOAPIC: setting id to 0x%x", newid));
	set_id (newid);
	return;
      }
    case 0x01: // version
    case 0x02: // arbitration id
      BX_INFO(("IOAPIC: could not write, IOREGSEL=0x%02x", ioregsel));
      return;
    default:
      int index = (ioregsel - 0x10) >> 1;
      if (index >= 0 && index < BX_IOAPIC_NUM_PINS) {
	bx_io_redirect_entry_t *entry = ioredtbl + index;
	if (ioregsel&1)
	  entry->set_hi_part(*value);
	else
	  entry->set_lo_part(*value);
	char buf[1024];
	entry->sprintf_self(buf);
	BX_DEBUG(("IOAPIC: now entry[%d] is %s", index, buf));
	service_ioapic();
	return;
      }
      BX_PANIC(("IOAPIC: IOREGSEL points to undefined register %02x", ioregsel));
  }
}

void bx_ioapic_c::set_irq_level(Bit8u int_in, bx_bool level)
{
  BX_DEBUG(("set_irq_level(): INTIN%d: level=%d", int_in, level));
  if (int_in < BX_IOAPIC_NUM_PINS) {
    Bit32u bit = 1<<int_in;
    if ((level<<int_in) != (intin & bit)) {
      bx_io_redirect_entry_t *entry = ioredtbl + int_in;
      if (entry->trigger_mode()) {
        // level triggered
        if (level) {
          intin |= bit;
          irr |= bit;
          service_ioapic();
        } else {
          intin &= ~bit;
          irr &= ~bit;
        }
      } else {
        // edge triggered
        if (level) {
          intin |= bit;
          irr |= bit;
          service_ioapic();
        } else {
          intin &= ~bit;
        }
      }
    }
  }
}

void bx_ioapic_c::receive_eoi(Bit8u vector)
{
  BX_DEBUG(("IOAPIC: received EOI for vector %d", vector));
}

void bx_ioapic_c::service_ioapic()
{
  static unsigned int stuck = 0;
  Bit8u vector = 0;
  // look in IRR and deliver any interrupts that are not masked.
  BX_DEBUG(("IOAPIC: servicing"));
  for (unsigned bit=0; bit < BX_IOAPIC_NUM_PINS; bit++) {
    Bit32u mask = 1<<bit;
    if (irr & mask) {
      bx_io_redirect_entry_t *entry = ioredtbl + bit;
      if (! entry->is_masked()) {
        // clear irr bit and deliver
        if (entry->delivery_mode() == 7) {
          vector = DEV_pic_iac();
        } else {
          vector = entry->vector();
        }
        bx_bool done = apic_bus_deliver_interrupt(vector, entry->destination(), entry->delivery_mode(), entry->destination_mode(), entry->pin_polarity(), entry->trigger_mode());
        if (done) {
          if (! entry->trigger_mode())
            irr &= ~mask;
          entry->clear_delivery_status();
          stuck = 0;
        } else {
          entry->set_delivery_status();
          stuck++;
          if (stuck > 5)
            BX_INFO(("vector %#x stuck?", vector));
        }
      }
      else {
        BX_DEBUG(("service_ioapic(): INTIN%d is masked", bit));
      }
    }
  }
}

#if BX_SUPPORT_SAVE_RESTORE
void bx_ioapic_c::register_state(void)
{
  bx_list_c *list = new bx_list_c(SIM->get_sr_root(), "ioapic", "IOAPIC State");
  BXRS_HEX_PARAM_SIMPLE(list, ioregsel);
  BXRS_HEX_PARAM_SIMPLE(list, intin);
  BXRS_HEX_PARAM_SIMPLE(list, irr);

  bx_list_c *table = new bx_list_c(list, "ioredtbl", BX_IOAPIC_NUM_PINS);
  for (unsigned i=0; i<BX_IOAPIC_NUM_PINS; i++) {
    char name[6];
    sprintf(name, "0x%02x", i);
    bx_list_c *entry = new bx_list_c(table, name, 2);
    ioredtbl[i].register_state(entry);
  }
}
#endif

#endif /* if BX_SUPPORT_APIC */
<|endoftext|>


<commit_before>#if !defined(DOUBLETAKE_XSYNC_H)
#define DOUBLETAKE_XSYNC_H

/*
 * @file   xsync.h
 * @brief  Mapping between pthread_t and internal thread information.
 * @author Tongping Liu <http://www.cs.umass.edu/~tonyliu>
 */

#include <assert.h>
#include <pthread.h>
#include <stddef.h>

#include "globalinfo.hh"
#include "hashfuncs.hh"
#include "hashmap.hh"
#include "internalheap.hh"
#include "list.hh"
#include "log.hh"
#include "mm.hh"
#include "recordentries.hh"
#include "semaphore.hh"
#include "spinlock.hh"
#include "synceventlist.hh"
#include "threadstruct.hh"
#include "xdefines.hh"

// deferSync should be implemented here, not threadinfo.hh
// However, those thread spawning or joinning should be kept at threainfo.hh.
// When a synchronization variable has been destroyed, we should not invoke another
// malloc. Thus,
class xsync {
public:
  struct SyncEntry {
		list_t listactive;
		list_t listnew;
		list_t listdel;
		syncVariableType type;
    void * nominal;
		void * real;
    SyncEventList* syncevents;
  };

private:
	class NewSyncvarList {
		public:
			void initialization(void) {
				listInit(&_list);
			}

			void insertTail(struct SyncEntry * entry) {
				listInsertTail(&entry->listnew, &_list);
			}

			struct SyncEntry * getSyncEntry(list_t * listentry) {
				return (struct SyncEntry *)((intptr_t)listentry - sizeof(list_t));
			}

			// Reinitialize the list in the epochBegin.
			// We don't care about original entries in the list since those
			// entries are also in the other list, which will be handled correpondingly.
			void cleanup(void) {
				listInit(&_list);
			}

			// Retrieve the first entry in the list (after _currentry);
			// Since we would like to support the endless replays, thus, whenever
			// we find an entry, we will move the current entry into the tail of the list.
			// Thus, we hope that we will have the same list after one round.
			struct SyncEntry * retrieveSyncEntry(syncVariableType type, void * nominal) {
				struct SyncEntry * entry = NULL;
				struct SyncEntry * target = NULL;
				list_t * last = _list.prev;
				list_t * next = NULL;

				// If the list is empty, trigger an assertion.
				if(isListEmpty(&_list)) {
					PRINF("the listnew should not be empty!\n");
					assert(0);
				}

				// Now we will search the whole list from the beginning.
				next = _list.next;

				while(true) {
					// Get the synchronization entry according to list pointer.
					entry = getSyncEntry(next);

					// Check whether the current entry is what we want.
					// In most cases, it is the truth. However, if two threads are initiating two
					// different variables in the same epoch, those initialization may be invoked in
					// a different order in replay phase. We should handle that as well.
					if(entry->type == type && entry->nominal == nominal) {
						target = entry;

						// remove current node.
						listRemoveNode(&entry->listnew);

						// Insert this node into the end of the list.
						insertTail(target);
						break;
					}

					// If we have searched the whole list, we will quit as well.
					if(next == last) {
						break;
					}

					// Otherwise, we will check the next one.
					next = next->next;
				}

				assert(target != NULL);

				return target;
			}

		private:
			list_t  _list;
	};

public:
  xsync() {}

	static xsync& getInstance() {
    static char buf[sizeof(xsync)];
    static xsync* theOneTrueObject = new (buf) xsync();
    return *theOneTrueObject;
  }

  void initialize() {
		// Initialize two lists for record synchronization variables.
 		listInit(&_activeList);
 		listInit(&_delList);

		_newList.initialization();

		Real::pthread_mutex_init(&_mutex, NULL);
  }

  struct SyncEntry * recordSyncVar(syncVariableType type, void* nominal, void* real, SyncEventList* list) {
		// Alloc a synchronization variable entry.
    struct SyncEntry* entry =
        (struct SyncEntry*)InternalHeap::getInstance().malloc(sizeof(struct SyncEntry));
		entry->type = type;
    entry->real = real;
    entry->nominal = nominal;
    entry->syncevents = list;

		lock();

		// record this synchronization variables on two lists
    listInsertTail(&entry->listactive, &_activeList);

		// Insert this into new list.
		_newList.insertTail(entry);

		unlock();

		return entry;
  }

	void freeSyncEntry(struct SyncEntry * entry) {
		InternalHeap::getInstance().free((void *)entry);
	}

	void deferSync(struct SyncEntry *entry) {
		lock();
		listInsertTail(&entry->listdel, &_delList);
		unlock();
	}

	struct SyncEntry * getSyncEntryDellist(list_t * listentry) {
		return (struct SyncEntry *)((intptr_t)listentry - sizeof(list_t) - sizeof(list_t));
	}

	void removeFromDellist(struct SyncEntry * entry) {
		listRemoveNode(&entry->listdel);
	}

	void removeFromAlllist(struct SyncEntry * entry) {
		listRemoveNode(&entry->listactive);
	}

	// In the rollback phase, we will fetch synchronization entry
	// during the initialization of every sync variable
	void * retrieveRealSyncEntry(syncVariableType type, void * nominal) {
		struct SyncEntry * entry = NULL;
		lock();
		entry =  _newList.retrieveSyncEntry(type, nominal);
		unlock();

		return entry->real;
	}

	// During the begin of an epoch
	void epochBegin(void) {
		struct SyncEntry * entry = NULL;
		list_t * last = NULL;
		list_t * next = NULL;
		list_t * now = NULL;

		// Cleanup every entry in _delList.
		if(!isListEmpty(&_delList)) {
			// Now we will search the whole list from the beginning.
			last = _delList.prev;
			now = _delList.next;

			while(true) {
				next = now->next;

				// Get the synchronization entry according to list pointer.
				entry = getSyncEntryDellist(now);

				// We will remove the entry from deleted list and activelist.
				removeFromDellist(entry);
				removeFromAlllist(entry);

				// Now we can remove this entry.
				freeSyncEntry(entry);

				if(now == last) {
					break;
				}

				// Get the next entry;
				now = next;
			}
		}

		// Cleanup all entries in the _newList
		// there is no new entries in the beginning of an epoch
		_newList.cleanup();

		// Updating the eventlist for all existing synchronization variables
		if(!isListEmpty(&_activeList)) {
			// Now we will search the whole list from the beginning.
			last = _activeList.prev;
			now = _activeList.next;

			while(true) {
				next = now->next;

				// Get the synchronization entry according to list pointer.
				entry = (struct SyncEntry *)now;

				// Cleanup the sync events on this synchronization variable since
				// we will record new ones in the new epoch
      	entry->syncevents->cleanup();

				if(now == last) {
					break;
				}
			}
		}

	}

  // Signal next thread on the same synchronization variable.
  static void signalNextThread(struct syncEvent* event) {
    thread_t* thread = (thread_t*)event->thread;

		// Acquire the lock before adding an event to the pending list
		// since the thread may try to check whether it can proceed or not
    lock_thread(thread);

    // Add this pending event into corresponding thread.
    // Whether this event is on the top of thread?
    if(isThreadNextEvent(event, thread)) {
      // If yes, signal to this thread. There is no difference between
      // current thread or other thread.
      PRINF("Thread %d actually signal next thread %d on event %p", current->index, thread->index, event);
      signalThread(thread);
    } else {
      PRINF("Thread %d adding pending event to next thread %d on event %p", current->index,
            thread->index, event);
      addPendingSyncEvent(event, thread);
    }

		unlock_thread(thread);
  }

	// Update the synchronization list.
  void advanceThreadSyncList() {
    lock_thread(current);

    // Update next event of thread eventlist.
    current->syncevents.advanceEntry();

    unlock_thread(current);
  }

  // Signal current thread if event is one of pending events.
  void signalCurrentThread(struct syncEvent* event) {
    thread_t* thread = (thread_t*)event->thread;
    list_t* eventlist = &thread->pendingSyncevents;

    lock_thread(current);

		// Having pending events
    if(!isListEmpty(eventlist)) {
		PRINF("During peek, calling singalCurrentThread %d. with pending events.\n", thread->index);
      // Signal itself when current event is first event of this thread.
      struct pendingSyncEvent* pe = NULL;

      // Search the whole list for given tid.
      pe = (struct pendingSyncEvent*)nextEntry(eventlist);
      while(true) {
        // We found this event
        if(pe->event == event) {
          PRINF("singalCurrentThread: signal myself thread %d, retrieve event %p pe->event %p", current->index, event, pe->event);
          // Remove this event from the list.
          listRemoveNode(&pe->list);

          // Release corresponding memory to avoid memory leakage.
          InternalHeap::getInstance().free(pe);

          // Now signal current thread.
          signalThread(thread);

					PRINF("singalCurrentThread %d: event %p", thread->index, event);
          break;
        }

        // Update to the next thread.
        if(isListTail(&pe->list, eventlist)) {
          break;
        } else {
          pe = (struct pendingSyncEvent*)nextEntry(&pe->list);
        }
      } // while (true)
    } else {
      PRINF("signalCurrentThread %d: thread pending list is empty now!!!", thread->index);
    }

		unlock_thread(current);
  }

	/*  Peek the synchronization event (first event in the thread), it will confirm the following things
       1. Whether this event is expected event? If it is not, maybe it is caused by
          a race condition. Maybe we should restart the rollback or just simply reported this problem.
       2. Whether the first event is on the pending list, which means it is the thread's turn?
          If yes, then the current signal thread should increment its semaphore.
       3. Whether the mutex_lock is successful or not? If it is not successful,
          no need to wait for the semaphore since there is no actual lock happens.
	*/
  inline int peekSyncEvent(void* tlist) {
    int result = -1;
		PRINF("thread %d(%p): peekSyncEvent targetlist %p\n", current->index, current, tlist);
		PRINF("thread %d syncevents %p: peekSyncEvent targetlist %p\n", current->index, &current->syncevents, tlist);
    struct syncEvent* event = (struct syncEvent*)current->syncevents.getEntry();
		PRINF("thread %d: peek event %p targetlist %p\n", current->index, event, tlist);

		// For debugging purpose.
		// If the event pointing to a different thread, or the target event
		// is not the current one, warn about this situaion. Something wrong!
		if((event == NULL) || (event->thread != current) || (event->eventlist != tlist)) {
			PRINF("Assertion:peekSyncEvent at thread %d: event %p event thread %d. eventlist %p targetlist %p\n", current->index, event, ((thread_t*)event->thread)->index, event->eventlist, tlist);
			while(1) ;
			assert(event->thread == current);
			assert(event->eventlist == tlist);
		}

		// Signal current thread if the event is in the pending list
    signalCurrentThread(event);

	  result = event->ret;
    return result;
  }

  /*
   Prepare rollback. Only one thread can call this function.
   It basically check every synchronization variable.
   If a synchronization variable is in the head of a thread, then
   we try to UP corresponding thread's semaphore.
   */
  void prepareRollback() {
    struct SyncEntry* entry;
		list_t * next;
		list_t * last = _activeList.prev;

		// If list is empty, return immediately.
		if(isListEmpty(&_activeList)) {
			return;
		}

		next = _activeList.next;
		while(true) {
			entry = (struct SyncEntry*)next;
			PRINF("prepareRollback syncvariable %p pointintto %p entry %p, eventlist %p\n", entry->nominal, entry->real, entry, entry->syncevents);

      prepareEventListRollback(entry->syncevents);

			// If we have traverse the whole list, let's quit now.
			if(next == last) {
				break;
			}

			// Check the next entry;
			next = next->next;
    }
  }

  /*
    Prepare the rollback for an event list.
    It will check whether the first event in the event list is also the head of specific
    thread. If yes, then we will signal specific thread so that this thread can acquire
    the semaphore immediately.
   */
  static void prepareEventListRollback(SyncEventList* eventlist) {
    struct syncEvent* event = eventlist->prepareRollback();

		PRINF("prepareEventListRollback eventlist %p event %p\n", eventlist, event);
    if(event) {
      // Signal to next thread with the top event
      signalNextThread(event);
    }
  }

  // Add one synchronization event into the pending list of a thread.
  static void addPendingSyncEvent(struct syncEvent* event, thread_t* thread) {
    struct pendingSyncEvent* pendingEvent = NULL;

    pendingEvent = (struct pendingSyncEvent*)InternalHeap::getInstance().malloc(
        sizeof(struct pendingSyncEvent));

    listInit(&pendingEvent->list);
    pendingEvent->event = event;

    listInsertTail(&pendingEvent->list, &thread->pendingSyncevents);
  }

  // Check whether this event is the first event of corresponding thread.
  static bool isThreadNextEvent(struct syncEvent* event, thread_t* thread) {
    return (event == thread->syncevents.firstIterEntry());
  }

  static void signalThread(thread_t* thread) {
    semaphore* sema = &thread->sema;
    PRINF("Thread %d: ^^^^^Signal semaphore to thread %d\n", current->index, thread->index);
    sema->put();
  }

private:

	void lock(void) {
		Real::pthread_mutex_lock(&_mutex);
	}

	void unlock(void) {
		Real::pthread_mutex_unlock(&_mutex);
	}

	pthread_mutex_t _mutex;

	// We are keeping track of three different list.
	// One is the new list, the second one is delete list.
	// The other one is alllist.
	NewSyncvarList _newList;

	// Active list for synchronization variables.
	list_t  _activeList;
	list_t  _delList;
};

#endif
<commit_msg>Fixed one small bug at xsync.<commit_after>#if !defined(DOUBLETAKE_XSYNC_H)
#define DOUBLETAKE_XSYNC_H

/*
 * @file   xsync.h
 * @brief  Mapping between pthread_t and internal thread information.
 * @author Tongping Liu <http://www.cs.umass.edu/~tonyliu>
 */

#include <assert.h>
#include <pthread.h>
#include <stddef.h>

#include "globalinfo.hh"
#include "hashfuncs.hh"
#include "hashmap.hh"
#include "internalheap.hh"
#include "list.hh"
#include "log.hh"
#include "mm.hh"
#include "recordentries.hh"
#include "semaphore.hh"
#include "spinlock.hh"
#include "synceventlist.hh"
#include "threadstruct.hh"
#include "xdefines.hh"

// deferSync should be implemented here, not threadinfo.hh
// However, those thread spawning or joinning should be kept at threainfo.hh.
// When a synchronization variable has been destroyed, we should not invoke another
// malloc. Thus,
class xsync {
public:
  struct SyncEntry {
		list_t listactive;
		list_t listnew;
		list_t listdel;
		syncVariableType type;
    void * nominal;
		void * real;
    SyncEventList* syncevents;
  };

private:
	class NewSyncvarList {
		public:
			void initialization(void) {
				listInit(&_list);
			}

			void insertTail(struct SyncEntry * entry) {
				listInsertTail(&entry->listnew, &_list);
			}

			struct SyncEntry * getSyncEntry(list_t * listentry) {
				return (struct SyncEntry *)((intptr_t)listentry - sizeof(list_t));
			}

			// Reinitialize the list in the epochBegin.
			// We don't care about original entries in the list since those
			// entries are also in the other list, which will be handled correpondingly.
			void cleanup(void) {
				listInit(&_list);
			}

			// Retrieve the first entry in the list (after _currentry);
			// Since we would like to support the endless replays, thus, whenever
			// we find an entry, we will move the current entry into the tail of the list.
			// Thus, we hope that we will have the same list after one round.
			struct SyncEntry * retrieveSyncEntry(syncVariableType type, void * nominal) {
				struct SyncEntry * entry = NULL;
				struct SyncEntry * target = NULL;
				list_t * last = _list.prev;
				list_t * next = NULL;

				// If the list is empty, trigger an assertion.
				if(isListEmpty(&_list)) {
					PRINF("the listnew should not be empty!\n");
					assert(0);
				}

				// Now we will search the whole list from the beginning.
				next = _list.next;

				while(true) {
					// Get the synchronization entry according to list pointer.
					entry = getSyncEntry(next);

					// Check whether the current entry is what we want.
					// In most cases, it is the truth. However, if two threads are initiating two
					// different variables in the same epoch, those initialization may be invoked in
					// a different order in replay phase. We should handle that as well.
					if(entry->type == type && entry->nominal == nominal) {
						target = entry;

						// remove current node.
						listRemoveNode(&entry->listnew);

						// Insert this node into the end of the list.
						insertTail(target);
						break;
					}

					// If we have searched the whole list, we will quit as well.
					if(next == last) {
						break;
					}

					// Otherwise, we will check the next one.
					next = next->next;
				}

				assert(target != NULL);

				return target;
			}

		private:
			list_t  _list;
	};

public:
  xsync() {}

	static xsync& getInstance() {
    static char buf[sizeof(xsync)];
    static xsync* theOneTrueObject = new (buf) xsync();
    return *theOneTrueObject;
  }

  void initialize() {
		// Initialize two lists for record synchronization variables.
 		listInit(&_activeList);
 		listInit(&_delList);

		_newList.initialization();

		Real::pthread_mutex_init(&_mutex, NULL);
  }

  struct SyncEntry * recordSyncVar(syncVariableType type, void* nominal, void* real, SyncEventList* list) {
		// Alloc a synchronization variable entry.
    struct SyncEntry* entry =
        (struct SyncEntry*)InternalHeap::getInstance().malloc(sizeof(struct SyncEntry));
		entry->type = type;
    entry->real = real;
    entry->nominal = nominal;
    entry->syncevents = list;

		lock();

		// record this synchronization variables on two lists
    listInsertTail(&entry->listactive, &_activeList);

		// Insert this into new list.
		_newList.insertTail(entry);

		unlock();

		return entry;
  }

	void freeSyncEntry(struct SyncEntry * entry) {
		InternalHeap::getInstance().free((void *)entry);
	}

	void deferSync(struct SyncEntry *entry) {
		lock();
		listInsertTail(&entry->listdel, &_delList);
		unlock();
	}

	struct SyncEntry * getSyncEntryDellist(list_t * listentry) {
		return (struct SyncEntry *)((intptr_t)listentry - sizeof(list_t) - sizeof(list_t));
	}

	void removeFromDellist(struct SyncEntry * entry) {
		listRemoveNode(&entry->listdel);
	}

	void removeFromAlllist(struct SyncEntry * entry) {
		listRemoveNode(&entry->listactive);
	}

	// In the rollback phase, we will fetch synchronization entry
	// during the initialization of every sync variable
	void * retrieveRealSyncEntry(syncVariableType type, void * nominal) {
		struct SyncEntry * entry = NULL;
		lock();
		entry =  _newList.retrieveSyncEntry(type, nominal);
		unlock();

		return entry->real;
	}

	// During the begin of an epoch
	void epochBegin(void) {
		struct SyncEntry * entry = NULL;
		list_t * last = NULL;
		list_t * next = NULL;
		list_t * now = NULL;

		// Cleanup every entry in _delList.
		if(!isListEmpty(&_delList)) {
			// Now we will search the whole list from the beginning.
			last = _delList.prev;
			now = _delList.next;

			while(true) {
				next = now->next;

				// Get the synchronization entry according to list pointer.
				entry = getSyncEntryDellist(now);

				// We will remove the entry from deleted list and activelist.
				removeFromDellist(entry);
				removeFromAlllist(entry);

				// Now we can remove this entry.
				freeSyncEntry(entry);

				if(now == last) {
					break;
				}

				// Get the next entry;
				now = next;
			}
		}

		// Cleanup all entries in the _newList
		// there is no new entries in the beginning of an epoch
		_newList.cleanup();

		// Updating the eventlist for all existing synchronization variables
		if(!isListEmpty(&_activeList)) {
			// Now we will search the whole list from the beginning.
			last = _activeList.prev;
			now = _activeList.next;

			while(true) {
				next = now->next;

				// Get the synchronization entry according to list pointer.
				entry = (struct SyncEntry *)now;

				// Cleanup the sync events on this synchronization variable since
				// we will record new ones in the new epoch
      	entry->syncevents->cleanup();

				if(now == last) {
					break;
				}
				else {
					now = next;
				}
			}
		}

	}

  // Signal next thread on the same synchronization variable.
  static void signalNextThread(struct syncEvent* event) {
    thread_t* thread = (thread_t*)event->thread;

		// Acquire the lock before adding an event to the pending list
		// since the thread may try to check whether it can proceed or not
    lock_thread(thread);

    // Add this pending event into corresponding thread.
    // Whether this event is on the top of thread?
    if(isThreadNextEvent(event, thread)) {
      // If yes, signal to this thread. There is no difference between
      // current thread or other thread.
      PRINF("Thread %d actually signal next thread %d on event %p", current->index, thread->index, event);
      signalThread(thread);
    } else {
      PRINF("Thread %d adding pending event to next thread %d on event %p", current->index,
            thread->index, event);
      addPendingSyncEvent(event, thread);
    }

		unlock_thread(thread);
  }

	// Update the synchronization list.
  void advanceThreadSyncList() {
    lock_thread(current);

    // Update next event of thread eventlist.
    current->syncevents.advanceEntry();

    unlock_thread(current);
  }

  // Signal current thread if event is one of pending events.
  void signalCurrentThread(struct syncEvent* event) {
    thread_t* thread = (thread_t*)event->thread;
    list_t* eventlist = &thread->pendingSyncevents;

    lock_thread(current);

		// Having pending events
    if(!isListEmpty(eventlist)) {
		PRINF("During peek, calling singalCurrentThread %d. with pending events.\n", thread->index);
      // Signal itself when current event is first event of this thread.
      struct pendingSyncEvent* pe = NULL;

      // Search the whole list for given tid.
      pe = (struct pendingSyncEvent*)nextEntry(eventlist);
      while(true) {
        // We found this event
        if(pe->event == event) {
          PRINF("singalCurrentThread: signal myself thread %d, retrieve event %p pe->event %p", current->index, event, pe->event);
          // Remove this event from the list.
          listRemoveNode(&pe->list);

          // Release corresponding memory to avoid memory leakage.
          InternalHeap::getInstance().free(pe);

          // Now signal current thread.
          signalThread(thread);

					PRINF("singalCurrentThread %d: event %p", thread->index, event);
          break;
        }

        // Update to the next thread.
        if(isListTail(&pe->list, eventlist)) {
          break;
        } else {
          pe = (struct pendingSyncEvent*)nextEntry(&pe->list);
        }
      } // while (true)
    } else {
      PRINF("signalCurrentThread %d: thread pending list is empty now!!!", thread->index);
    }

		unlock_thread(current);
  }

	/*  Peek the synchronization event (first event in the thread), it will confirm the following things
       1. Whether this event is expected event? If it is not, maybe it is caused by
          a race condition. Maybe we should restart the rollback or just simply reported this problem.
       2. Whether the first event is on the pending list, which means it is the thread's turn?
          If yes, then the current signal thread should increment its semaphore.
       3. Whether the mutex_lock is successful or not? If it is not successful,
          no need to wait for the semaphore since there is no actual lock happens.
	*/
  inline int peekSyncEvent(void* tlist) {
    int result = -1;
		PRINF("thread %d(%p): peekSyncEvent targetlist %p\n", current->index, current, tlist);
		PRINF("thread %d syncevents %p: peekSyncEvent targetlist %p\n", current->index, &current->syncevents, tlist);
    struct syncEvent* event = (struct syncEvent*)current->syncevents.getEntry();
		PRINF("thread %d: peek event %p targetlist %p\n", current->index, event, tlist);

		// For debugging purpose.
		// If the event pointing to a different thread, or the target event
		// is not the current one, warn about this situaion. Something wrong!
		if((event == NULL) || (event->thread != current) || (event->eventlist != tlist)) {
			PRINF("Assertion:peekSyncEvent at thread %d: event %p event thread %d. eventlist %p targetlist %p\n", current->index, event, ((thread_t*)event->thread)->index, event->eventlist, tlist);
			while(1) ;
			assert(event->thread == current);
			assert(event->eventlist == tlist);
		}

		// Signal current thread if the event is in the pending list
    signalCurrentThread(event);

	  result = event->ret;
    return result;
  }

  /*
   Prepare rollback. Only one thread can call this function.
   It basically check every synchronization variable.
   If a synchronization variable is in the head of a thread, then
   we try to UP corresponding thread's semaphore.
   */
  void prepareRollback() {
    struct SyncEntry* entry;
		list_t * next;
		list_t * last = _activeList.prev;

		// If list is empty, return immediately.
		if(isListEmpty(&_activeList)) {
			return;
		}

		next = _activeList.next;
		while(true) {
			entry = (struct SyncEntry*)next;
			PRINF("prepareRollback syncvariable %p pointintto %p entry %p, eventlist %p\n", entry->nominal, entry->real, entry, entry->syncevents);

      prepareEventListRollback(entry->syncevents);

			// If we have traverse the whole list, let's quit now.
			if(next == last) {
				break;
			}

			// Check the next entry;
			next = next->next;
    }
  }

  /*
    Prepare the rollback for an event list.
    It will check whether the first event in the event list is also the head of specific
    thread. If yes, then we will signal specific thread so that this thread can acquire
    the semaphore immediately.
   */
  static void prepareEventListRollback(SyncEventList* eventlist) {
    struct syncEvent* event = eventlist->prepareRollback();

		PRINF("prepareEventListRollback eventlist %p event %p\n", eventlist, event);
    if(event) {
      // Signal to next thread with the top event
      signalNextThread(event);
    }
  }

  // Add one synchronization event into the pending list of a thread.
  static void addPendingSyncEvent(struct syncEvent* event, thread_t* thread) {
    struct pendingSyncEvent* pendingEvent = NULL;

    pendingEvent = (struct pendingSyncEvent*)InternalHeap::getInstance().malloc(
        sizeof(struct pendingSyncEvent));

    listInit(&pendingEvent->list);
    pendingEvent->event = event;

    listInsertTail(&pendingEvent->list, &thread->pendingSyncevents);
  }

  // Check whether this event is the first event of corresponding thread.
  static bool isThreadNextEvent(struct syncEvent* event, thread_t* thread) {
    return (event == thread->syncevents.firstIterEntry());
  }

  static void signalThread(thread_t* thread) {
    semaphore* sema = &thread->sema;
    PRINF("Thread %d: ^^^^^Signal semaphore to thread %d\n", current->index, thread->index);
    sema->put();
  }

private:

	void lock(void) {
		Real::pthread_mutex_lock(&_mutex);
	}

	void unlock(void) {
		Real::pthread_mutex_unlock(&_mutex);
	}

	pthread_mutex_t _mutex;

	// We are keeping track of three different list.
	// One is the new list, the second one is delete list.
	// The other one is alllist.
	NewSyncvarList _newList;

	// Active list for synchronization variables.
	list_t  _activeList;
	list_t  _delList;
};

#endif
<|endoftext|>


<commit_before>#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "ui/addcomputer.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    createAllTabs();
    createTimer();
}
MainWindow::~MainWindow()
{
    deleteAllTabs();
    delete timer;
    delete ui;
}
//We use the timer to check if user has tried to add data to the program.
void MainWindow::createTimer()
{
    timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(checkDataAdded()));
    timer->start(500); //time specified in ms
}

void MainWindow::hardCodePictureToDB()
{
    /*
    QString filename = "no-image-available.png";
    QFile file("../../Computers/computer scientists/" + filename);
    if (file.open(QIODevice::ReadOnly))
    {
        qDebug() << "Could Open File";
        QByteArray inByteArray = file.readAll();
        _service.onlyAddPicturetoDB(filename.toStdString(),inByteArray);//Uncomment this line to write Picture to database.
    }
    */
}
void MainWindow::createAllTabs()
{
    ui->tabWidget_MainWindow->removeTab(1);//Remove second (index 1) tab so we can edit it the rest here.
    _showList = new ShowList(this);
    _addComputerScientist = new AddComputerScientist(this);
    _addComputer = new AddComputer(this);
    _addType = new AddType(this);
    _showTrash = new ShowTrash(this);

    ui->tabWidget_MainWindow->addTab(_showList,"Show List");
    ui->tabWidget_MainWindow->addTab(_addComputerScientist,"Add CS");
    ui->tabWidget_MainWindow->addTab(_addComputer,"Add Comp");
    ui->tabWidget_MainWindow->addTab(_addType,"Add Type");
    ui->tabWidget_MainWindow->addTab(_showTrash,"Show Recycle");
    //ui->tabWidget_MainWindow->addTab(tTIW,*(new QIcon(":/icons/images/computer2_icon.png")), tr("Tab Name"));//How to add QIcon
}

void MainWindow::deleteAllTabs()
{
    delete _showList;
    delete _addComputerScientist;
    delete _addComputer;
    delete _addType;
    delete _showTrash;
}

//Toolbar
void MainWindow::goHome()
{
    ui->tabWidget_MainWindow->setCurrentIndex(constants::TAB_HOME);//Head back home
}

void MainWindow::on_action_toolbar_Home_triggered()
{
    //TODO - Refresh all data before entering.
    goHome();
}

void MainWindow::on_action_toolbar_Show_List_triggered()
{
    //Send our data into the show list tab before we open it.
    _showList->setList(_service.getComputerScientistList(_filterSearch), _service.getComputerList(_filterSearch));
    ui->tabWidget_MainWindow->setCurrentIndex(constants::TAB_SHOW_LIST);
    refreshAllTables();
}

void MainWindow::on_actionAdd_Computer_Scientist_triggered()
{
    _addComputerScientist->resetAllData();
    _addComputerScientist->setComputersList(_service.getComputerList(_filterSearch));
    ui->tabWidget_MainWindow->setCurrentIndex(constants::TAB_ADD_CS);
    refreshAllTables();
}

void MainWindow::on_action_toolbar_Add_Computer__triggered()
{
    _addComputer->clearFields();
    _addComputer->resetData();
    _addComputer->setComputerType(_service.getComputerTypesList());
    _addComputer->setComputerScientistList(_service.getComputerScientistList(_filterSearch));
    _addComputer->setComputerTypesComboBox();
    ui->tabWidget_MainWindow->setCurrentIndex(constants::TAB_ADD_COMPUTER);
    refreshAllTables();
}

void MainWindow::on_actionAdd_Computer_Type_triggered()
{
    _addType->clearFields();
    _addType->resetData();
    _addType->setTypes(_service.getComputerTypesList());//Sending computer types so we can check if this type already exist.
    ui->tabWidget_MainWindow->setCurrentIndex(constants::TAB_ADD_TYPE);
    refreshAllTables();
}
void MainWindow::on_action_toolbar_Trash_triggered()
{
    _showTrash->setTrashList(_service.getComputerScientistTrash(_filterSearch), _service.getComputerTrash(_filterSearch));
    ui->tabWidget_MainWindow->setCurrentIndex(constants::TAB_SHOW_RECYCLE_BIN);
    refreshAllTables();
}
void MainWindow::on_actionExit_triggered()
{
    QCoreApplication::quit();
}

//Check if data is needed to be inserted into the database.
void MainWindow::checkDataAdded()
{
    //If Computer Scientist was added.
    if(_addComputerScientist->result())//If Add computer scientist was valid.
    {
        addNewScientist();
        _addComputerScientist->setResult(false);//Set result back to false
        goHome();
    }
    //If Computer was added.
    if(_addComputer->result())
    {
        addNewComputer();
        _addComputer->setResult(false);
        goHome();
    }
    //If computer type was added
    if(_addType->result())
    {
        addNewType();
        _addType->setResult(false);
        goHome();
    }
    //If we are going to restore some data
    if(_showTrash->result())
    {
        if(_showTrash->getCompOrScientistToRestore() == constants::COMPUTER_SCIENTIST)
        {
            restoreComputerScientist();
            _showTrash->setResult(false);
        }
        else//Restore computer
        {
            restoreComputer();
            _showTrash->setResult(false);
        }
    }
    //If we are going to remove some data
    if(_showList->result())
    {
        if(_showList->getIfToRemoveComputer() == constants::COMPUTER)
        {
            _service.removeComputerFromList(to_string(_showList->getIdToRemove()));
        }
        else
        {
            _service.removePersonFromList(to_string(_showList->getIdToRemove()));
        }
        _showList->setList(_service.getComputerScientistList(_filterSearch), _service.getComputerList(_filterSearch));
        _showList->setResult(false);
    }
}
void MainWindow::addNewScientist()
{

    CSPerson newScientist = _addComputerScientist->getPerson();
    _service.addNewPersonToList(_addComputerScientist->getComputersConnected(),\
                                newScientist.getName(),\
                                newScientist.getGender(),\
                                to_string(newScientist.getBirthYear()),\
                                to_string(newScientist.getPassedAwayYear()),\
                                newScientist.getComments(),\
                                _addComputerScientist->getImageName(),\
                                _addComputerScientist->getImage());
}
void MainWindow::addNewComputer()
{
    Computer newComputer = _addComputer->getComputer();
    _service.addNewComputerToList(_addComputer->getCSconntedToComp(),\
                                  newComputer.getName(),\
                                  newComputer.getDesignYear(),\
                                  newComputer.getBuildYear(),\
                                  newComputer.getTypeID(),\
                                  newComputer.getIsCreated(),\
                                  _addComputer->getImageName(),\
                                  _addComputer->getImage());
}
void MainWindow::addNewType()
{
    _service.addComputerType(_addType->getTypeName());
}
void MainWindow::restoreComputerScientist()
{
    _service.restorePersonToList(_showTrash->getCSidToRestore());
    _showTrash->setTrashList(_service.getComputerScientistTrash(_filterSearch), _service.getComputerTrash(_filterSearch));
}
void MainWindow::restoreComputer()
{
    _service.restoreComputerToList(_showTrash->getComputerIDToRestore());
    _showTrash->setTrashList(_service.getComputerScientistTrash(_filterSearch), _service.getComputerTrash(_filterSearch));
}

void MainWindow::on_TextBox_Search_textChanged()
{
    _filterSearch = ui->TextBox_Search->text().toStdString();
    refreshAllTables();
}
void MainWindow::refreshAllTables()
{
        _showList->setList(_service.getComputerScientistList(_filterSearch), _service.getComputerList(_filterSearch));
        _addComputerScientist->resetAllData();
        _addComputerScientist->setComputersList(_service.getComputerList(_filterSearch));
        _addComputer->clearFields();
        _addComputer->resetData();
        _addComputer->setComputerType(_service.getComputerTypesList());
        _addComputer->setComputerScientistList(_service.getComputerScientistList(_filterSearch));
        _addComputer->setComputerTypesComboBox();
        _showTrash->setTrashList(_service.getComputerScientistTrash(_filterSearch), _service.getComputerTrash(_filterSearch));
}
<commit_msg>used the wrong function to refresh tables, removed them<commit_after>#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "ui/addcomputer.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    createAllTabs();
    createTimer();
}
MainWindow::~MainWindow()
{
    deleteAllTabs();
    delete timer;
    delete ui;
}
//We use the timer to check if user has tried to add data to the program.
void MainWindow::createTimer()
{
    timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(checkDataAdded()));
    timer->start(500); //time specified in ms
}

void MainWindow::hardCodePictureToDB()
{
    /*
    QString filename = "no-image-available.png";
    QFile file("../../Computers/computer scientists/" + filename);
    if (file.open(QIODevice::ReadOnly))
    {
        qDebug() << "Could Open File";
        QByteArray inByteArray = file.readAll();
        _service.onlyAddPicturetoDB(filename.toStdString(),inByteArray);//Uncomment this line to write Picture to database.
    }
    */
}
void MainWindow::createAllTabs()
{
    ui->tabWidget_MainWindow->removeTab(1);//Remove second (index 1) tab so we can edit it the rest here.
    _showList = new ShowList(this);
    _addComputerScientist = new AddComputerScientist(this);
    _addComputer = new AddComputer(this);
    _addType = new AddType(this);
    _showTrash = new ShowTrash(this);

    ui->tabWidget_MainWindow->addTab(_showList,"Show List");
    ui->tabWidget_MainWindow->addTab(_addComputerScientist,"Add CS");
    ui->tabWidget_MainWindow->addTab(_addComputer,"Add Comp");
    ui->tabWidget_MainWindow->addTab(_addType,"Add Type");
    ui->tabWidget_MainWindow->addTab(_showTrash,"Show Recycle");
    //ui->tabWidget_MainWindow->addTab(tTIW,*(new QIcon(":/icons/images/computer2_icon.png")), tr("Tab Name"));//How to add QIcon
}

void MainWindow::deleteAllTabs()
{
    delete _showList;
    delete _addComputerScientist;
    delete _addComputer;
    delete _addType;
    delete _showTrash;
}

//Toolbar
void MainWindow::goHome()
{
    ui->tabWidget_MainWindow->setCurrentIndex(constants::TAB_HOME);//Head back home
}

void MainWindow::on_action_toolbar_Home_triggered()
{
    //TODO - Refresh all data before entering.
    goHome();
}

void MainWindow::on_action_toolbar_Show_List_triggered()
{
    //Send our data into the show list tab before we open it.
    _showList->setList(_service.getComputerScientistList(_filterSearch), _service.getComputerList(_filterSearch));
    ui->tabWidget_MainWindow->setCurrentIndex(constants::TAB_SHOW_LIST);
}

void MainWindow::on_actionAdd_Computer_Scientist_triggered()
{
    _addComputerScientist->resetAllData();
    _addComputerScientist->setComputersList(_service.getComputerList(_filterSearch));
    ui->tabWidget_MainWindow->setCurrentIndex(constants::TAB_ADD_CS);
}

void MainWindow::on_action_toolbar_Add_Computer__triggered()
{
    _addComputer->clearFields();
    _addComputer->resetData();
    _addComputer->setComputerType(_service.getComputerTypesList());
    _addComputer->setComputerScientistList(_service.getComputerScientistList(_filterSearch));
    _addComputer->setComputerTypesComboBox();
    ui->tabWidget_MainWindow->setCurrentIndex(constants::TAB_ADD_COMPUTER);
}

void MainWindow::on_actionAdd_Computer_Type_triggered()
{
    _addType->clearFields();
    _addType->resetData();
    _addType->setTypes(_service.getComputerTypesList());//Sending computer types so we can check if this type already exist.
    ui->tabWidget_MainWindow->setCurrentIndex(constants::TAB_ADD_TYPE);
}
void MainWindow::on_action_toolbar_Trash_triggered()
{
    _showTrash->setTrashList(_service.getComputerScientistTrash(_filterSearch), _service.getComputerTrash(_filterSearch));
    ui->tabWidget_MainWindow->setCurrentIndex(constants::TAB_SHOW_RECYCLE_BIN);
}
void MainWindow::on_actionExit_triggered()
{
    QCoreApplication::quit();
}

//Check if data is needed to be inserted into the database.
void MainWindow::checkDataAdded()
{
    //If Computer Scientist was added.
    if(_addComputerScientist->result())//If Add computer scientist was valid.
    {
        addNewScientist();
        _addComputerScientist->setResult(false);//Set result back to false
        goHome();
    }
    //If Computer was added.
    if(_addComputer->result())
    {
        addNewComputer();
        _addComputer->setResult(false);
        goHome();
    }
    //If computer type was added
    if(_addType->result())
    {
        addNewType();
        _addType->setResult(false);
        goHome();
    }
    //If we are going to restore some data
    if(_showTrash->result())
    {
        if(_showTrash->getCompOrScientistToRestore() == constants::COMPUTER_SCIENTIST)
        {
            restoreComputerScientist();
            _showTrash->setResult(false);
        }
        else//Restore computer
        {
            restoreComputer();
            _showTrash->setResult(false);
        }
    }
    //If we are going to remove some data
    if(_showList->result())
    {
        if(_showList->getIfToRemoveComputer() == constants::COMPUTER)
        {
            _service.removeComputerFromList(to_string(_showList->getIdToRemove()));
        }
        else
        {
            _service.removePersonFromList(to_string(_showList->getIdToRemove()));
        }
        _showList->setList(_service.getComputerScientistList(_filterSearch), _service.getComputerList(_filterSearch));
        _showList->setResult(false);
    }
}
void MainWindow::addNewScientist()
{

    CSPerson newScientist = _addComputerScientist->getPerson();
    _service.addNewPersonToList(_addComputerScientist->getComputersConnected(),\
                                newScientist.getName(),\
                                newScientist.getGender(),\
                                to_string(newScientist.getBirthYear()),\
                                to_string(newScientist.getPassedAwayYear()),\
                                newScientist.getComments(),\
                                _addComputerScientist->getImageName(),\
                                _addComputerScientist->getImage());
}
void MainWindow::addNewComputer()
{
    Computer newComputer = _addComputer->getComputer();
    _service.addNewComputerToList(_addComputer->getCSconntedToComp(),\
                                  newComputer.getName(),\
                                  newComputer.getDesignYear(),\
                                  newComputer.getBuildYear(),\
                                  newComputer.getTypeID(),\
                                  newComputer.getIsCreated(),\
                                  _addComputer->getImageName(),\
                                  _addComputer->getImage());
}
void MainWindow::addNewType()
{
    _service.addComputerType(_addType->getTypeName());
}
void MainWindow::restoreComputerScientist()
{
    _service.restorePersonToList(_showTrash->getCSidToRestore());
    _showTrash->setTrashList(_service.getComputerScientistTrash(_filterSearch), _service.getComputerTrash(_filterSearch));
}
void MainWindow::restoreComputer()
{
    _service.restoreComputerToList(_showTrash->getComputerIDToRestore());
    _showTrash->setTrashList(_service.getComputerScientistTrash(_filterSearch), _service.getComputerTrash(_filterSearch));
}

void MainWindow::on_TextBox_Search_textChanged()
{
    _filterSearch = ui->TextBox_Search->text().toStdString();
    refreshAllTables();
}
void MainWindow::refreshAllTables()
{
        _showList->setList(_service.getComputerScientistList(_filterSearch), _service.getComputerList(_filterSearch));
        _addComputerScientist->resetAllData();
        _addComputerScientist->setComputersList(_service.getComputerList(_filterSearch));
        _addComputer->clearFields();
        _addComputer->resetData();
        _addComputer->setComputerType(_service.getComputerTypesList());
        _addComputer->setComputerScientistList(_service.getComputerScientistList(_filterSearch));
        _addComputer->setComputerTypesComboBox();
        _showTrash->setTrashList(_service.getComputerScientistTrash(_filterSearch), _service.getComputerTrash(_filterSearch));
}
<|endoftext|>


<commit_before>#include <chrono>
#include <ctime>
#include <fstream>
#include <iostream>
#include <map>
#include <queue>
#include <ratio>
#include <string>
#include <stdlib.h>
#include <time.h>
#include "omp.h"
#include <vector>

#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/classification.hpp>
#include "boost/lexical_cast.hpp"

using namespace boost::algorithm;

#include "pass_runner.h"

#define NUM_THREADS 8 // default number of threads
#define MAX_NUM_PER_THREAD 16

#if(0)
#ifdef DEBUG
#ifndef TIME
#define TIME
#endif
#endif
#endif

using namespace std;
using namespace std::chrono;

/*------- GLOBAL VARIABES --------*/
// vector with permutations of passorder
vector<string> passOrder;
char *binaryName;
char *binaryArgs;
char *input_combination_file;
string dir_name;

#define _SYSTEM_CALL( CMD ) ( {            \
    int err = ( system( CMD.c_str() ) );   \
    if ( err < 0  ) {                      \
        fprintf(stderr, #CMD, " failed."); \
        abort();                           \
    }                                      \
    err;                                   \
})                                         \

class BoundMap {
  public:
    BoundMap() { };

    bool in_range(){
      if(pq.size() < MAX_NUM_PER_THREAD) return true;
      return false;
    }

    void insert(string s, double d){
      if(in_range()){
        pq.push(RECORD(s,d));

      } else if(pq.top().exec_time > d) {
        pq.pop();
        pq.push(RECORD(s,d));
      }

#ifdef BMAP_DEBUG
      std::cout << "Inserting new element with time "<< d << ". Size " << pq.size() << " Worst time " << pq.top().exec_time << " Sequence: " << pq.top().pass_order << std::endl;
#endif

    } /* end of function insert */

    void insert(RECORD r){
      if(in_range()){
        pq.push(r);

      } else if(pq.top().exec_time > r.exec_time) {
        pq.pop();
        pq.push(r);
      }
    }

    PQUEUE pq;
};

inline COMMAND::COMMAND(string pass_order, long double threadId) {
  // opt -pass1 -pass2 ./bcfile -o temp.out.threadId >> /dev/null

  string pname = " ";// = A::PASS_MAP[0];
  vector<string> strs;
  boost::split(strs,pass_order,boost::is_any_of(" "));

  for(vector<string>::iterator pit = strs.begin(); pit != strs.end(); ++pit){
    string pass_num_string = *pit;
    int pnumber = atoi(pass_num_string.c_str());
    pname = pname + " " + A::PASS_MAP[pnumber];
  }
#ifdef DEBUG
  cout << pname << endl;
#endif
  // combination_file_name/temp.out.input_combination_filename
  string temp_name = dir_name + string("/temp.out.") + input_combination_file;

  opt = string("opt ") + pname + " ./"  + binaryName + " -o "+ temp_name  + "" + to_string(threadId) + " >> /dev/null";
  // Command to execute the file.
  //
  //    lli = string("lli ") + temp_name + to_string(threadId) + " " + binaryArgs + to_string(threadId);
  lli = string("/Users/ankit/DevelopmentKits/build/bin/lli ") + temp_name + to_string(threadId) + " " + binaryArgs + to_string(threadId);
}

void cleanUpTheMess() {
  string rm_command = string("rm -rf ") + dir_name;

#ifdef DEBUG
  cout << "Cleaning temporary files.." << endl;
  cout << "Running Command: " << rm_command << endl;
#endif
  _SYSTEM_CALL ( rm_command) ;
}

void runOptimizationPasses() {
  //map<string, double> optExecMap;

  map<long double, BoundMap> boundMaps;
  BoundMap bmap;
  clock_t t1,t2;
  float diff;
  long double tid;

#pragma omp parallel for private(t1, t2, diff, tid, bmap)
  for( int i = 0; i < passOrder.size() ; ++i ) {
    tid = omp_get_thread_num();
    clock_t t1,t2;

    // Run the passes with order from file.
    COMMAND Cmd(passOrder[i], tid);

#ifdef DEBUG
    cout << "Running Command: " << Cmd.opt << "\n" << Cmd.lli  << " in thread number " << tid << endl;
#endif

    //        _SYSTEM_CALL( Cmd.opt );

    double start = omp_get_wtime( );

    t1 = clock();
    _SYSTEM_CALL( (Cmd.opt + " && " +Cmd.lli) );

    t2 = clock();
    double diff = (double)t2 - (double)t1;

    double end = omp_get_wtime( );

    bmap.insert( passOrder[i], (end-start) );
    boundMaps[tid] = bmap;
    //optExecMap.insert( pair<string, double>(passOrder[i], (32.4) ) );
  }

  // Merge data from all threads
  BoundMap finalBmap;

  for (map<long double, BoundMap>::iterator it = boundMaps.begin(); it != boundMaps.end(); ++it) {
    BoundMap BM = it->second;
    PQUEUE pq = BM.pq;
    while(!pq.empty()){
      RECORD rec = pq.top();
      pq.pop();
      finalBmap.insert(rec);
    }
  }

  std::cout << finalBmap.pq.size() << std::endl;

#ifdef TIME
  for (map<string, double>::iterator it = optExecMap.begin(); it != optExecMap.end() ; ++it) {
    std::cout << it->first << " : " << it->second << std::endl;
  }
#endif

  cleanUpTheMess();
}

int main(int argc, char** argv) {

  int numThreads = NUM_THREADS;

  if(argc > 1) {
    binaryName = argv[1];
    input_combination_file = argv[2];
    binaryArgs = argv[3];
    numThreads = atoi(argv[4]);
    //        std::cout << binaryName << " " << binaryArgs << " " << numThreads << " " <<input_combination_file << endl;
  } else {
    std::cout << "Usage: pass_runner <Binary Name> <NumThreads(optional)>" << std::endl;
    abort();
  }

  // open a file in read mode.
  ifstream infile;
  infile.open(input_combination_file);

  string opt_order;
  while(getline(infile, opt_order)) {
    passOrder.push_back(opt_order);
  }

  // this will potentially print the contents of events.1 file
#ifdef VERBOSE
  cout << passOrder;
#endif

  // set openmp number of threads
  omp_set_num_threads(numThreads);

  dir_name = string(input_combination_file) + "dir";
  string create_dir_cmd = string("mkdir ") + dir_name;
  _SYSTEM_CALL(create_dir_cmd );

  runOptimizationPasses();

  return EXIT_SUCCESS;
}
<commit_msg>adding time print and fixing machine specific command path<commit_after>#include <chrono>
#include <ctime>
#include <fstream>
#include <iostream>
#include <map>
#include <queue>
#include <ratio>
#include <string>
#include <stdlib.h>
#include <time.h>
#include "omp.h"
#include <vector>

#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/classification.hpp>
#include "boost/lexical_cast.hpp"

using namespace boost::algorithm;

#include "pass_runner.h"

#define NUM_THREADS 8 // default number of threads
#define MAX_NUM_PER_THREAD 16

#if(0)
#ifdef DEBUG
#ifndef TIME
#define TIME
#endif
#endif
#endif

using namespace std;
using namespace std::chrono;

/*------- GLOBAL VARIABES --------*/
// vector with permutations of passorder
vector<string> passOrder;
char *binaryName;
char *binaryArgs;
char *input_combination_file;
string dir_name;

#define _SYSTEM_CALL( CMD ) ( {            \
    int err = ( system( CMD.c_str() ) );   \
    if ( err < 0  ) {                      \
        fprintf(stderr, #CMD, " failed."); \
        abort();                           \
    }                                      \
    err;                                   \
})                                         \

class BoundMap {
  public:
    BoundMap() { };

    bool in_range(){
      if(pq.size() < MAX_NUM_PER_THREAD) return true;
      return false;
    }

    void insert(string s, double d){
      if(in_range()){
        pq.push(RECORD(s,d));

      } else if(pq.top().exec_time > d) {
        pq.pop();
        pq.push(RECORD(s,d));
      }

#ifdef BMAP_DEBUG
      std::cout << "Inserting new element with time "<< d << ". Size " << pq.size() << " Worst time " << pq.top().exec_time << " Sequence: " << pq.top().pass_order << std::endl;
#endif

    } /* end of function insert */

    void insert(RECORD r){
      if(in_range()){
        pq.push(r);

      } else if(pq.top().exec_time > r.exec_time) {
        pq.pop();
        pq.push(r);
      }
    }

    PQUEUE pq;
};

inline COMMAND::COMMAND(string pass_order, long double threadId) {
  // opt -pass1 -pass2 ./bcfile -o temp.out.threadId >> /dev/null

  string pname = " ";// = A::PASS_MAP[0];
  vector<string> strs;
  boost::split(strs,pass_order,boost::is_any_of(" "));

  for(vector<string>::iterator pit = strs.begin(); pit != strs.end(); ++pit){
    string pass_num_string = *pit;
    int pnumber = atoi(pass_num_string.c_str());
    pname = pname + " " + A::PASS_MAP[pnumber];
  }
#ifdef DEBUG
  cout << pname << endl;
#endif
  // combination_file_name/temp.out.input_combination_filename
  string temp_name = dir_name + string("/temp.out.") + input_combination_file;

  opt = string("opt ") + pname + " ./"  + binaryName + " -o "+ temp_name  + "" + to_string(threadId) + " >> /dev/null";
  // Command to execute the file.
  //
  //    lli = string("lli ") + temp_name + to_string(threadId) + " " + binaryArgs + to_string(threadId);
  lli = string("lli ") + temp_name + to_string(threadId) + " " + binaryArgs + to_string(threadId);
}

void cleanUpTheMess() {
  string rm_command = string("rm -rf ") + dir_name;

#ifdef DEBUG
  cout << "Cleaning temporary files.." << endl;
  cout << "Running Command: " << rm_command << endl;
#endif
  _SYSTEM_CALL ( rm_command) ;
}

void runOptimizationPasses() {
  //map<string, double> optExecMap;

  map<long double, BoundMap> boundMaps;
  BoundMap bmap;
  clock_t t1,t2;
  float diff;
  long double tid;

#pragma omp parallel for private(t1, t2, diff, tid, bmap)
  for( int i = 0; i < passOrder.size() ; ++i ) {
    tid = omp_get_thread_num();
    clock_t t1,t2;

    // Run the passes with order from file.
    COMMAND Cmd(passOrder[i], tid);

#ifdef DEBUG
    cout << "Running Command: " << Cmd.opt << "\n" << Cmd.lli  << " in thread number " << tid << endl;
#endif

    //        _SYSTEM_CALL( Cmd.opt );

    double start = omp_get_wtime( );

    t1 = clock();
    _SYSTEM_CALL( (Cmd.opt + " && " +Cmd.lli) );

    t2 = clock();
    double diff = (double)t2 - (double)t1;

    double end = omp_get_wtime( );

    bmap.insert( passOrder[i], (end-start) );
    boundMaps[tid] = bmap;
    //optExecMap.insert( pair<string, double>(passOrder[i], (32.4) ) );
  }

  // Merge data from all threads
  BoundMap finalBmap;

  for (map<long double, BoundMap>::iterator it = boundMaps.begin(); it != boundMaps.end(); ++it) {
    BoundMap BM = it->second;
    PQUEUE pq = BM.pq;
    while(!pq.empty()){
      RECORD rec = pq.top();
      pq.pop();
      finalBmap.insert(rec);
    }
  }

  std::cout << finalBmap.pq.size() << std::endl;

#ifdef TIME
  PQUEUE pq = finalBmap.pq;
  while(!pq.empty()) {
    RECORD rec = pq.top();
    pq.pop();
    cout << rec.pass_order << ":"  <<  rec.exec_time << "\n";
  }
#endif

  cleanUpTheMess();
}

int main(int argc, char** argv) {

  int numThreads = NUM_THREADS;

  if(argc > 1) {
    binaryName = argv[1];
    input_combination_file = argv[2];
    binaryArgs = argv[3];
    numThreads = atoi(argv[4]);
    //        std::cout << binaryName << " " << binaryArgs << " " << numThreads << " " <<input_combination_file << endl;
  } else {
    std::cout << "Usage: pass_runner <Binary Name> <NumThreads(optional)>" << std::endl;
    abort();
  }

  // open a file in read mode.
  ifstream infile;
  infile.open(input_combination_file);

  string opt_order;
  while(getline(infile, opt_order)) {
    passOrder.push_back(opt_order);
  }

  // this will potentially print the contents of events.1 file
#ifdef VERBOSE
  cout << passOrder;
#endif

  // set openmp number of threads
  omp_set_num_threads(numThreads);

  dir_name = string(input_combination_file) + "dir";
  string create_dir_cmd = string("mkdir ") + dir_name;
  _SYSTEM_CALL(create_dir_cmd );

  runOptimizationPasses();

  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

// <regex>
// UNSUPPORTED: c++98, c++03

// Make sure that we correctly match inverted character classes.

#include <cassert>
#include <regex>

#include "test_macros.h"

int main(int, char**) {
    assert(std::regex_match("X", std::regex("[X]")));
    assert(std::regex_match("X", std::regex("[XY]")));
    assert(!std::regex_match("X", std::regex("[^X]")));
    assert(!std::regex_match("X", std::regex("[^XY]")));

    assert(std::regex_match("X", std::regex("[\\S]")));
    assert(!std::regex_match("X", std::regex("[^\\S]")));

    assert(!std::regex_match("X", std::regex("[\\s]")));
    assert(std::regex_match("X", std::regex("[^\\s]")));

    assert(std::regex_match("X", std::regex("[\\s\\S]")));
    assert(std::regex_match("X", std::regex("[^Y\\s]")));
    assert(!std::regex_match("X", std::regex("[^X\\s]")));

    assert(std::regex_match("X", std::regex("[\\w]")));
    assert(std::regex_match("_", std::regex("[\\w]")));
    assert(!std::regex_match("X", std::regex("[^\\w]")));
    assert(!std::regex_match("_", std::regex("[^\\w]")));

    assert(!std::regex_match("X", std::regex("[\\W]")));
    assert(!std::regex_match("_", std::regex("[\\W]")));
    assert(std::regex_match("X", std::regex("[^\\W]")));
    assert(std::regex_match("_", std::regex("[^\\W]")));

    // Those test cases are taken from PR40904
    assert(std::regex_match("abZcd", std::regex("^ab[\\d\\D]cd")));
    assert(std::regex_match("ab5cd", std::regex("^ab[\\d\\D]cd")));
    assert(std::regex_match("abZcd", std::regex("^ab[\\D]cd")));
    assert(std::regex_match("abZcd", std::regex("^ab\\Dcd")));
    assert(std::regex_match("ab5cd", std::regex("^ab[\\d]cd")));
    assert(std::regex_match("ab5cd", std::regex("^ab\\dcd")));
    assert(!std::regex_match("abZcd", std::regex("^ab\\dcd")));
    assert(!std::regex_match("ab5cd", std::regex("^ab\\Dcd")));

    return 0;
}
<commit_msg>[libc++] Add yet another test for inverted character classes<commit_after>//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

// <regex>
// UNSUPPORTED: c++98, c++03

// Make sure that we correctly match inverted character classes.

#include <cassert>
#include <regex>

#include "test_macros.h"

int main(int, char**) {
    assert(std::regex_match("X", std::regex("[X]")));
    assert(std::regex_match("X", std::regex("[XY]")));
    assert(!std::regex_match("X", std::regex("[^X]")));
    assert(!std::regex_match("X", std::regex("[^XY]")));

    assert(std::regex_match("X", std::regex("[\\S]")));
    assert(!std::regex_match("X", std::regex("[^\\S]")));

    assert(!std::regex_match("X", std::regex("[\\s]")));
    assert(std::regex_match("X", std::regex("[^\\s]")));

    assert(std::regex_match("X", std::regex("[\\s\\S]")));
    assert(std::regex_match("X", std::regex("[^Y\\s]")));
    assert(!std::regex_match("X", std::regex("[^X\\s]")));

    assert(std::regex_match("X", std::regex("[\\w]")));
    assert(std::regex_match("_", std::regex("[\\w]")));
    assert(!std::regex_match("X", std::regex("[^\\w]")));
    assert(!std::regex_match("_", std::regex("[^\\w]")));

    assert(!std::regex_match("X", std::regex("[\\W]")));
    assert(!std::regex_match("_", std::regex("[\\W]")));
    assert(std::regex_match("X", std::regex("[^\\W]")));
    assert(std::regex_match("_", std::regex("[^\\W]")));

    // Those test cases are taken from PR40904
    assert(std::regex_match("abZcd", std::regex("^ab[\\d\\D]cd")));
    assert(std::regex_match("ab5cd", std::regex("^ab[\\d\\D]cd")));
    assert(std::regex_match("abZcd", std::regex("^ab[\\D]cd")));
    assert(std::regex_match("abZcd", std::regex("^ab\\Dcd")));
    assert(std::regex_match("ab5cd", std::regex("^ab[\\d]cd")));
    assert(std::regex_match("ab5cd", std::regex("^ab\\dcd")));
    assert(!std::regex_match("abZcd", std::regex("^ab\\dcd")));
    assert(!std::regex_match("ab5cd", std::regex("^ab\\Dcd")));

    assert(std::regex_match("_xyz_", std::regex("_(\\s|\\S)+_")));
    assert(std::regex_match("_xyz_", std::regex("_[\\s\\S]+_")));

    return 0;
}
<|endoftext|>


<commit_before>//
// Copyright (C) 2007 SIPez LLC.
// Licensed to SIPfoundry under a Contributor Agreement.
//
// Copyright (C) 2007 SIPfoundry Inc.
// Licensed by SIPfoundry under the LGPL license.
//
// $$
///////////////////////////////////////////////////////////////////////////////

#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/TestCase.h>
#include <sipxunit/TestUtilities.h>

#include <mp/MpOutputDeviceManager.h>
#include <mp/MpAudioBuf.h>
#include <mp/MpSineWaveGeneratorDeviceDriver.h>
#include <os/OsTask.h>
#include <os/OsEvent.h>

#ifdef RTL_ENABLED // [
#  include "rtl_macro.h"
#else  // RTL_ENABLED ][
#  define RTL_WRITE(x)
#  define RTL_BLOCK(x)
#  define RTL_START(x)
#  define RTL_STOP
#endif // RTL_ENABLED ]

#define TEST_SAMPLES_PER_FRAME_SIZE   80
#define BUFFER_NUM                    50
#define TEST_SAMPLES_PER_SECOND       8000
#define TEST_MIXER_BUFFER_LENGTH      10
#define TEST_SAMPLE_DATA_LENGTH_SEC   2  // test length in seconds
#define TEST_SAMPLE_DATA_SIZE         (TEST_SAMPLES_PER_SECOND*TEST_SAMPLE_DATA_LENGTH_SEC)
#define TEST_SAMPLE_DATA_MAGNITUDE    32000
#define TEST_SAMPLE_DATA_PERIOD       7  // in milliseconds

//#define USE_TEST_DRIVER

#ifdef USE_TEST_DRIVER // USE_TEST_DRIVER [
#include <mp/MpodBufferRecorder.h>
#define OUTPUT_DRIVER MpodBufferRecorder
#define OUTPUT_DRIVER_CONSTRUCTOR_PARAMS "default", TEST_SAMPLE_DATA_SIZE*1000/TEST_SAMPLES_PER_SECOND

#elif defined(WIN32) // USE_TEST_DRIVER ][ WIN32
#include <mp/MpodWinMM.h>
#define OUTPUT_DRIVER MpodWinMM
#define OUTPUT_DRIVER_CONSTRUCTOR_PARAMS MpodWinMM::getDefaultDeviceName()

#elif defined(__pingtel_on_posix__) // WIN32 ][ __pingtel_on_posix__
#include <mp/MpodOss.h>
#define OUTPUT_DRIVER MpodOss
#define OUTPUT_DRIVER_CONSTRUCTOR_PARAMS "/dev/dsp"

#else // __pingtel_on_possix__ ]
#error Unknown platform!
#endif

MpAudioSample sampleData[TEST_SAMPLE_DATA_SIZE];
UtlBoolean sampleDataInitialized=FALSE;

void calculateSampleData()
{
   if (sampleDataInitialized)
      return;

   for (int i=0; i<TEST_SAMPLE_DATA_SIZE; i++)
   {
      sampleData[i] =
         MpSineWaveGeneratorDeviceDriver::calculateSample(0,
                                                          TEST_SAMPLE_DATA_MAGNITUDE,
                                                          TEST_SAMPLE_DATA_PERIOD,
                                                          i,
                                                          TEST_SAMPLES_PER_FRAME_SIZE,
                                                          TEST_SAMPLES_PER_SECOND);
   }

   sampleDataInitialized = TRUE;
}

/**
 * Unittest for MpOutputDeviceManager
 */
class MpOutputFrameworkTest : public CppUnit::TestCase
{
   CPPUNIT_TEST_SUITE(MpOutputFrameworkTest);
   CPPUNIT_TEST(testCreate);
   CPPUNIT_TEST(testAddRemoveToManager);
   CPPUNIT_TEST(testEnableDisable);
   CPPUNIT_TEST(testEnableDisableFast);
   // This is disabled, as it gives very bad sound quality
   // and may be used only for very first driver testing.
   //CPPUNIT_TEST(testDirectWrite);
   CPPUNIT_TEST(testTickerNotification);
   CPPUNIT_TEST_SUITE_END();

public:

   void setUp()
   {
      // Create pool for data buffers
      mpPool = new MpBufPool(TEST_SAMPLES_PER_FRAME_SIZE * sizeof(MpAudioSample)
                             + MpArrayBuf::getHeaderSize(), BUFFER_NUM);
      CPPUNIT_ASSERT(mpPool != NULL);

      // Create pool for buffer headers
      mpHeadersPool = new MpBufPool(sizeof(MpAudioBuf), BUFFER_NUM);
      CPPUNIT_ASSERT(mpHeadersPool != NULL);

      // Set mpHeadersPool as default pool for audio and data pools.
      MpAudioBuf::smpDefaultPool = mpHeadersPool;
      MpDataBuf::smpDefaultPool = mpHeadersPool;
   }

   void tearDown()
   {
      if (mpPool != NULL)
      {
         delete mpPool;
      }
      if (mpHeadersPool != NULL)
      {
         delete mpHeadersPool;
      }
   }

   void testCreate()
   {
      OUTPUT_DRIVER driver(OUTPUT_DRIVER_CONSTRUCTOR_PARAMS);
   }

   void testAddRemoveToManager()
   {
      OUTPUT_DRIVER device(OUTPUT_DRIVER_CONSTRUCTOR_PARAMS);
      MpOutputDeviceHandle deviceId;

      {
         // Test with direct write mode
         MpOutputDeviceManager deviceManager(TEST_SAMPLES_PER_FRAME_SIZE,
            TEST_SAMPLES_PER_SECOND,
            0);

         deviceId = deviceManager.addDevice(&device);
         CPPUNIT_ASSERT(deviceId > 0);
         CPPUNIT_ASSERT(deviceManager.removeDevice(deviceId) == &device);
      }

      {
         // Test with mixer mode
         MpOutputDeviceManager deviceManager(TEST_SAMPLES_PER_FRAME_SIZE,
                                             TEST_SAMPLES_PER_SECOND,
                                             TEST_MIXER_BUFFER_LENGTH);

         deviceId = deviceManager.addDevice(&device);
         CPPUNIT_ASSERT(deviceId > 0);
         CPPUNIT_ASSERT(deviceManager.removeDevice(deviceId) == &device);
      }
   }

   void testEnableDisable()
   {
      OUTPUT_DRIVER driver(OUTPUT_DRIVER_CONSTRUCTOR_PARAMS);
      driver.enableDevice(TEST_SAMPLES_PER_FRAME_SIZE, TEST_SAMPLES_PER_SECOND, 0);
      OsTask::delay(50);
      driver.disableDevice();
   }

   void testEnableDisableFast()
   {
      OUTPUT_DRIVER driver(OUTPUT_DRIVER_CONSTRUCTOR_PARAMS);
      driver.enableDevice(TEST_SAMPLES_PER_FRAME_SIZE, TEST_SAMPLES_PER_SECOND, 0);
      driver.disableDevice();
   }

   void testDirectWrite()
   {
      calculateSampleData();

      OUTPUT_DRIVER driver(OUTPUT_DRIVER_CONSTRUCTOR_PARAMS);
      driver.enableDevice(TEST_SAMPLES_PER_FRAME_SIZE, TEST_SAMPLES_PER_SECOND, 0);

      // Write some data to device.
      for (int frame=0; frame<TEST_SAMPLE_DATA_SIZE/TEST_SAMPLES_PER_FRAME_SIZE; frame++)
      {
         OsTask::delay(1000*TEST_SAMPLES_PER_FRAME_SIZE/TEST_SAMPLES_PER_SECOND);
         driver.pushFrame(TEST_SAMPLES_PER_FRAME_SIZE, sampleData + TEST_SAMPLES_PER_FRAME_SIZE*frame, -1);
      }

      driver.disableDevice();
   }

   void testTickerNotification()
   {
      OsEvent notificationEvent;

      RTL_START(1000000);

      calculateSampleData();

      OUTPUT_DRIVER driver(OUTPUT_DRIVER_CONSTRUCTOR_PARAMS);
      driver.enableDevice(TEST_SAMPLES_PER_FRAME_SIZE, TEST_SAMPLES_PER_SECOND, 0);
      driver.setTickerNotification(&notificationEvent);

      // Write some data to device.
      for (int frame=0; frame<TEST_SAMPLE_DATA_SIZE/TEST_SAMPLES_PER_FRAME_SIZE; frame++)
      {
         notificationEvent.wait(OsTime(500));
         notificationEvent.reset();
         RTL_BLOCK("test ticker loop");
         driver.pushFrame(TEST_SAMPLES_PER_FRAME_SIZE, sampleData + TEST_SAMPLES_PER_FRAME_SIZE*frame, -1);
      }

      driver.disableDevice();

      RTL_WRITE("testTickerNotification.rtl");
      RTL_STOP
   }

protected:
   MpBufPool *mpPool;         ///< Pool for data buffers
   MpBufPool *mpHeadersPool;  ///< Pool for buffers headers

};

CPPUNIT_TEST_SUITE_REGISTRATION(MpOutputFrameworkTest);
<commit_msg>Remove direct-write mode test from MpOutputFrameworkTest - there are no more such mode.<commit_after>//
// Copyright (C) 2007 SIPez LLC.
// Licensed to SIPfoundry under a Contributor Agreement.
//
// Copyright (C) 2007 SIPfoundry Inc.
// Licensed by SIPfoundry under the LGPL license.
//
// $$
///////////////////////////////////////////////////////////////////////////////

#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/TestCase.h>
#include <sipxunit/TestUtilities.h>

#include <mp/MpOutputDeviceManager.h>
#include <mp/MpAudioBuf.h>
#include <mp/MpSineWaveGeneratorDeviceDriver.h>
#include <os/OsTask.h>
#include <os/OsEvent.h>

#ifdef RTL_ENABLED // [
#  include "rtl_macro.h"
#else  // RTL_ENABLED ][
#  define RTL_WRITE(x)
#  define RTL_BLOCK(x)
#  define RTL_START(x)
#  define RTL_STOP
#endif // RTL_ENABLED ]

#define TEST_SAMPLES_PER_FRAME_SIZE   80
#define BUFFER_NUM                    50
#define TEST_SAMPLES_PER_SECOND       8000
#define TEST_MIXER_BUFFER_LENGTH      10
#define TEST_SAMPLE_DATA_LENGTH_SEC   2  // test length in seconds
#define TEST_SAMPLE_DATA_SIZE         (TEST_SAMPLES_PER_SECOND*TEST_SAMPLE_DATA_LENGTH_SEC)
#define TEST_SAMPLE_DATA_MAGNITUDE    32000
#define TEST_SAMPLE_DATA_PERIOD       7  // in milliseconds

//#define USE_TEST_DRIVER

#ifdef USE_TEST_DRIVER // USE_TEST_DRIVER [
#include <mp/MpodBufferRecorder.h>
#define OUTPUT_DRIVER MpodBufferRecorder
#define OUTPUT_DRIVER_CONSTRUCTOR_PARAMS "default", TEST_SAMPLE_DATA_SIZE*1000/TEST_SAMPLES_PER_SECOND

#elif defined(WIN32) // USE_TEST_DRIVER ][ WIN32
#include <mp/MpodWinMM.h>
#define OUTPUT_DRIVER MpodWinMM
#define OUTPUT_DRIVER_CONSTRUCTOR_PARAMS MpodWinMM::getDefaultDeviceName()

#elif defined(__pingtel_on_posix__) // WIN32 ][ __pingtel_on_posix__
#include <mp/MpodOss.h>
#define OUTPUT_DRIVER MpodOss
#define OUTPUT_DRIVER_CONSTRUCTOR_PARAMS "/dev/dsp"

#else // __pingtel_on_possix__ ]
#error Unknown platform!
#endif

MpAudioSample sampleData[TEST_SAMPLE_DATA_SIZE];
UtlBoolean sampleDataInitialized=FALSE;

void calculateSampleData()
{
   if (sampleDataInitialized)
      return;

   for (int i=0; i<TEST_SAMPLE_DATA_SIZE; i++)
   {
      sampleData[i] =
         MpSineWaveGeneratorDeviceDriver::calculateSample(0,
                                                          TEST_SAMPLE_DATA_MAGNITUDE,
                                                          TEST_SAMPLE_DATA_PERIOD,
                                                          i,
                                                          TEST_SAMPLES_PER_FRAME_SIZE,
                                                          TEST_SAMPLES_PER_SECOND);
   }

   sampleDataInitialized = TRUE;
}

/**
 * Unittest for MpOutputDeviceManager
 */
class MpOutputFrameworkTest : public CppUnit::TestCase
{
   CPPUNIT_TEST_SUITE(MpOutputFrameworkTest);
   CPPUNIT_TEST(testCreate);
   CPPUNIT_TEST(testAddRemoveToManager);
   CPPUNIT_TEST(testEnableDisable);
   CPPUNIT_TEST(testEnableDisableFast);
   // This is disabled, as it gives very bad sound quality
   // and may be used only for very first driver testing.
   //CPPUNIT_TEST(testDirectWrite);
   CPPUNIT_TEST(testTickerNotification);
   CPPUNIT_TEST_SUITE_END();

public:

   void setUp()
   {
      // Create pool for data buffers
      mpPool = new MpBufPool(TEST_SAMPLES_PER_FRAME_SIZE * sizeof(MpAudioSample)
                             + MpArrayBuf::getHeaderSize(), BUFFER_NUM);
      CPPUNIT_ASSERT(mpPool != NULL);

      // Create pool for buffer headers
      mpHeadersPool = new MpBufPool(sizeof(MpAudioBuf), BUFFER_NUM);
      CPPUNIT_ASSERT(mpHeadersPool != NULL);

      // Set mpHeadersPool as default pool for audio and data pools.
      MpAudioBuf::smpDefaultPool = mpHeadersPool;
      MpDataBuf::smpDefaultPool = mpHeadersPool;
   }

   void tearDown()
   {
      if (mpPool != NULL)
      {
         delete mpPool;
      }
      if (mpHeadersPool != NULL)
      {
         delete mpHeadersPool;
      }
   }

   void testCreate()
   {
      OUTPUT_DRIVER driver(OUTPUT_DRIVER_CONSTRUCTOR_PARAMS);
   }

   void testAddRemoveToManager()
   {
      OUTPUT_DRIVER device(OUTPUT_DRIVER_CONSTRUCTOR_PARAMS);
      MpOutputDeviceHandle deviceId;

      // Test with mixer mode
      MpOutputDeviceManager deviceManager(TEST_SAMPLES_PER_FRAME_SIZE,
                                          TEST_SAMPLES_PER_SECOND,
                                          TEST_MIXER_BUFFER_LENGTH);

      deviceId = deviceManager.addDevice(&device);
      CPPUNIT_ASSERT(deviceId > 0);
      CPPUNIT_ASSERT(deviceManager.removeDevice(deviceId) == &device);
   }

   void testEnableDisable()
   {
      OUTPUT_DRIVER driver(OUTPUT_DRIVER_CONSTRUCTOR_PARAMS);
      driver.enableDevice(TEST_SAMPLES_PER_FRAME_SIZE, TEST_SAMPLES_PER_SECOND, 0);
      OsTask::delay(50);
      driver.disableDevice();
   }

   void testEnableDisableFast()
   {
      OUTPUT_DRIVER driver(OUTPUT_DRIVER_CONSTRUCTOR_PARAMS);
      driver.enableDevice(TEST_SAMPLES_PER_FRAME_SIZE, TEST_SAMPLES_PER_SECOND, 0);
      driver.disableDevice();
   }

   void testDirectWrite()
   {
      calculateSampleData();

      OUTPUT_DRIVER driver(OUTPUT_DRIVER_CONSTRUCTOR_PARAMS);
      driver.enableDevice(TEST_SAMPLES_PER_FRAME_SIZE, TEST_SAMPLES_PER_SECOND, 0);

      // Write some data to device.
      for (int frame=0; frame<TEST_SAMPLE_DATA_SIZE/TEST_SAMPLES_PER_FRAME_SIZE; frame++)
      {
         OsTask::delay(1000*TEST_SAMPLES_PER_FRAME_SIZE/TEST_SAMPLES_PER_SECOND);
         driver.pushFrame(TEST_SAMPLES_PER_FRAME_SIZE, sampleData + TEST_SAMPLES_PER_FRAME_SIZE*frame, -1);
      }

      driver.disableDevice();
   }

   void testTickerNotification()
   {
      OsEvent notificationEvent;

      RTL_START(1000000);

      calculateSampleData();

      OUTPUT_DRIVER driver(OUTPUT_DRIVER_CONSTRUCTOR_PARAMS);
      driver.enableDevice(TEST_SAMPLES_PER_FRAME_SIZE, TEST_SAMPLES_PER_SECOND, 0);
      driver.setTickerNotification(&notificationEvent);

      // Write some data to device.
      for (int frame=0; frame<TEST_SAMPLE_DATA_SIZE/TEST_SAMPLES_PER_FRAME_SIZE; frame++)
      {
         notificationEvent.wait(OsTime(500));
         notificationEvent.reset();
         RTL_BLOCK("test ticker loop");
         driver.pushFrame(TEST_SAMPLES_PER_FRAME_SIZE, sampleData + TEST_SAMPLES_PER_FRAME_SIZE*frame, -1);
      }

      driver.disableDevice();

      RTL_WRITE("testTickerNotification.rtl");
      RTL_STOP
   }

protected:
   MpBufPool *mpPool;         ///< Pool for data buffers
   MpBufPool *mpHeadersPool;  ///< Pool for buffers headers

};

CPPUNIT_TEST_SUITE_REGISTRATION(MpOutputFrameworkTest);
<|endoftext|>


<commit_before>#include "intfunction.h"
#include "exprcalc.h"
#include <cstring>

const size_t MAX_SIZE = 1000;

void IntFunction::copy(const IntFunction& other)
{
    name = other.name;
    param = other.param;

    expr = new char[strlen(other.expr) + 1];
    strcpy(expr, other.expr);
}

void IntFunction::destroy()
{
    delete[] expr;
}

bool IntFunction::parse(const char* dfn)
{
    // първо извличаме името (латинска буква)
    const char* i = find_token(dfn);
    if (!i || !is_alpha(*i))
        return false;
    name = *i;
    i++;

    // после извличаме '('
    i = find_token(i);
    if (!i || *i != '(')
        return false;
    i++;

    // след това извличаме името на аргумента
    i = find_token(i);
    if (!i || !is_alpha(*i))
        return false;
    param = *i;
    i++;

    // после извличаме ')'
    i = find_token(i);
    if (!i || *i != ')')
        return false;
    i++;

    // след това извличаме '='
    i = find_token(i);
    if (!i || *i != '=')
        return false;
    i++;

    // и накрая копираме израза в полето expr
    i = find_token(i);
    expr = new char[strlen(i) + 1];
    strcpy(expr, i);
    return true;
}

IntFunction::IntFunction(std::istream& in)
{
    char strin[MAX_SIZE];
    in.getline(strin, MAX_SIZE);
    parse(strin);
}

IntFunction::IntFunction(const char* dfn)
{
    parse(dfn);
}

IntFunction::IntFunction(const std::string& s)
{
    parse(s.c_str());
}

IntFunction::IntFunction(const IntFunction& other)
{
    copy(other);
}

IntFunction& IntFunction::operator=(const IntFunction& other)
{
    if (&other != this)
    {
        destroy();
        copy(other);
    }

    return *this;
}

IntFunction::~IntFunction()
{
    destroy();
}

int IntFunction::calculate(int arg) const
{
    strsubst(expr, param, arg);
    return calculate_expr(expr);
}
<commit_msg>rewrote calculate function to use std::string and the relevant parameter interpolation function (`interpolate`)<commit_after>#include "intfunction.h"
#include "exprcalc.h"
#include <cstring>

const size_t MAX_SIZE = 1000;

void IntFunction::copy(const IntFunction& other)
{
    name = other.name;
    param = other.param;

    expr = new char[strlen(other.expr) + 1];
    strcpy(expr, other.expr);
}

void IntFunction::destroy()
{
    delete[] expr;
}

bool IntFunction::parse(const char* dfn)
{
    // първо извличаме името (латинска буква)
    const char* i = find_token(dfn);
    if (!i || !is_alpha(*i))
        return false;
    name = *i;
    i++;

    // после извличаме '('
    i = find_token(i);
    if (!i || *i != '(')
        return false;
    i++;

    // след това извличаме името на аргумента
    i = find_token(i);
    if (!i || !is_alpha(*i))
        return false;
    param = *i;
    i++;

    // после извличаме ')'
    i = find_token(i);
    if (!i || *i != ')')
        return false;
    i++;

    // след това извличаме '='
    i = find_token(i);
    if (!i || *i != '=')
        return false;
    i++;

    // и накрая копираме израза в полето expr
    i = find_token(i);
    expr = new char[strlen(i) + 1];
    strcpy(expr, i);
    return true;
}

IntFunction::IntFunction(std::istream& in)
{
    char strin[MAX_SIZE];
    in.getline(strin, MAX_SIZE);
    parse(strin);
}

IntFunction::IntFunction(const char* dfn)
{
    parse(dfn);
}

IntFunction::IntFunction(const std::string& s)
{
    parse(s.c_str());
}

IntFunction::IntFunction(const IntFunction& other)
{
    copy(other);
}

IntFunction& IntFunction::operator=(const IntFunction& other)
{
    if (&other != this)
    {
        destroy();
        copy(other);
    }

    return *this;
}

IntFunction::~IntFunction()
{
    destroy();
}

int IntFunction::calculate(int arg) const
{
    //char* expr_int = new char[MAX_SIZE];
    //strcpy(expr_int, expr);
    std::string expr_int(expr);
    interpolate(expr_int, param, arg);
    return calculate_expr(expr_int.c_str());
    //delete[] expr_int;
    //return result;
}
<|endoftext|>