Skip to content

Commit

Permalink
Added makefile. Added DiLite src.
Browse files Browse the repository at this point in the history
  • Loading branch information
swlasse committed Apr 13, 2012
1 parent bfdbc99 commit 53aa88a
Show file tree
Hide file tree
Showing 14 changed files with 712 additions and 0 deletions.
18 changes: 18 additions & 0 deletions makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
CC=g++
CFLAGS= -c -Wall -ansi -pedantic
LDFLAGS=
SOURCES= src/main.cpp src/sword.cpp src/shuriken.cpp src/samurai.cpp src/factory.cpp
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=samurai
LIBS= -lboost_thread

all: $(SOURCES) $(EXECUTABLE)

$(EXECUTABLE): $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) $(LIBS) -o bin/$@

.cpp.o:
$(CC) $(CFLAGS) $< -o $@

clean:
rm -f src/*.o bin/$(EXECUTABLE)
161 changes: 161 additions & 0 deletions src/dilite/di.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
#ifndef BASEIOC_H
#define BASEIOC_H

#include <stdlib.h>
#include <sstream>
#include <map>
#include <typeinfo>
#include <iostream>
#include <stdexcept>
#include <string>
#include <stdarg.h>

#include "singleton.h"

namespace DiLite
{
/**
Template used to create instance of specific type T.
@return Void pointer to object instance.
*/
template<typename T> void* CreateInstance() { return new T; }

/**
The Dependency Injection (DI) container class.
@author SW801
*/
class BaseDI
{
private:
/** A map of <TypeId, function pointer> to create object instances */
std::map<std::string, void*(*)()> _objectConstructors;

/** A map of <TypeId, void pointer> to refer to singleton instances */
std::map<std::string, void*> _singletons;

/**
Checks if an object constructor or singleton of type I has been registered.
*/
template<typename I> void CheckExistence()
{
if(_singletons.find(typeid(I).name()) != _singletons.end() || _objectConstructors.find(typeid(I).name()) != _objectConstructors.end())
throw std::runtime_error(((std::string) typeid(I).name()) + " is already bound.");
}

/**
Type parameter constraint: checks that T is derived from B
Courtesy of: Bjarne Stroustrup,
http://www2.research.att.com/~bs/bs_faq2.html#constraints
*/
template<class T, class B> struct Derived_from
{
static void constraints(T* p)
{
B* pb = p;
}
Derived_from()
{
void(*p)(T*) = constraints;
}
};

public:
/**
Bind type I in transient scope using construction function.
Each time resolved, a new instance is created and returned.
@param pt2func Function pointer to construction function.
*/
template<typename I> void Bind(I*(*pt2func)())
{
CheckExistence<I>();
_objectConstructors[typeid(I).name()] = (void*(*)())pt2func;
}

/**
Bind type I to type T in transient scope using default constructor of T.
Each time resolved, a new instance is created and returned.
*/
template<typename I, typename T> void Bind()
{
Derived_from<T,I>();
CheckExistence<I>();
_objectConstructors[typeid(I).name()] = &CreateInstance<T>;
}

/**
Bind type I to type T in singleton scope using default constructor of T.
Each time resolved, the same instance is returned.
*/
template<typename I, typename T> void BindSingle()
{
Derived_from<T,I>();
CheckExistence<I>();
_singletons[typeid(I).name()] = &Singleton<T>::GetInstance();
}

/**
Bind type I to type T in singleton scope using construction function.
Each time resolved, the same instance is returned.
@param pt2func Function pointer to construction function.
*/
template<typename I, typename T> void BindSingle(I*(*pt2func)())
{
Derived_from<T,I>();
CheckExistence<I>();
_singletons[typeid(I).name()] = &Singleton<T>::CreateInstance((void*(*)())pt2func);
}

/**
Resolve an instance of the desired type/interface.
Object may be pre-existing if registered as singleton.
Otherwise lazily constructed using an object constructor.
*/
template<typename I> I* Resolve()
{
// Check if "resolvable" from singleton scope
if(_singletons.find(typeid(I).name()) != _singletons.end())
return ((I*)_singletons[typeid(I).name()]);

// Check if "resolvable" from transient scope
if(_objectConstructors.find(typeid(I).name()) != _objectConstructors.end())
return ((I*)_objectConstructors[typeid(I).name()]());

// Binding not found
throw std::runtime_error(((std::string) typeid(I).name()) + " is not bound.");
}

/**
Unbinds every registered object constructor and singleton instance.
*/
template<typename I> void Unbind()
{
// Unbind all objects in transient scope
std::map<std::string, void*(*)()>::iterator it_transients = _objectConstructors.find(typeid(I).name());

if (it_transients != _objectConstructors.end())
{
_objectConstructors.erase(it_transients);
}

// Unbind all objects in singleton scope
std::map<std::string, void*>::iterator it_singletons = _singletons.find(typeid(I).name());

if (it_singletons != _singletons.end())
{
_singletons.erase(it_singletons);
}
}
};

/**
Typedefinition of the Singleton DI container.
*/
typedef Singleton<BaseDI> DI;
}

#endif
73 changes: 73 additions & 0 deletions src/dilite/singleton.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#ifndef SINGLETON_H_SW8
#define SINGLETON_H_SW8

#include <cassert>
#include <boost/thread/mutex.hpp>

namespace DiLite
{
/**
Template for any class that should be in
singleton scope.
*/
template<typename T> class Singleton
{
private:
/** Indicates if the singleton has been destructed */
static bool _isDestructed;

/** The mutex used by the singleton to enable thread-safety */
static boost::mutex& GetMutex()
{
static boost::mutex mutex;
return mutex;
}

/** Prevent construction of Singleton class */
Singleton() {}

/** Prevent destruction of Singleton class */
~Singleton() { _isDestructed = true; }

/** Prevent copy of Singleton */
Singleton(Singleton const&);

/** Prevent assignment to Singleton */
void operator=(Singleton const&);

public:
/**
Gets the instance wrapped by the Singleton.
@return A singleton object of type T.
*/
static T& GetInstance()
{
assert(!_isDestructed);
boost::mutex::scoped_lock lock(GetMutex());
static T instance;
return instance;
}

/**
Creates and gets an instance of type T in singleton scope.
@param ctor A function pointer to a construction function returning T.
@return A singleton object of type T.
*/
static T& CreateInstance(void*(*ctor)())
{
assert(!_isDestructed);
boost::mutex::scoped_lock lock(GetMutex());
static T instance = *((T*)ctor());
return instance;
}
};

/**
Force creation of the mutex before main() is called.
This happens as a consequence of the comma-operator and semantics of sequence points.
*/
template<typename T> bool Singleton<T>::_isDestructed = (Singleton<T>::GetMutex(), false);
}
#endif
11 changes: 11 additions & 0 deletions src/factory.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#include "factory.h"
#include "i_weapon.h"
#include "samurai.h"

namespace SampleCode
{
IWarrior* Factory::CreateSamurai()
{
return new Samurai(DiLite::DI::GetInstance().Resolve<IWeapon>());
}
}
27 changes: 27 additions & 0 deletions src/factory.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#ifndef FACTORY_H
#define FACTORY_H

#include "dilite/di.h"
#include "i_warrior.h"

namespace SampleCode
{
/**
A factory class to instantiate objects in the program.
Provides coupling between the running program and the
DI framework.
@author SW801
*/
class Factory
{
public:
/**
Creates a new Samurai using the DI framework.
@return IWarrior pointer to the Samurai object.
*/
static IWarrior* CreateSamurai();
};
}
#endif
74 changes: 74 additions & 0 deletions src/i_warrior.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#ifndef I_WARRIOR
#define I_WARRIOR

#include <string>

namespace SampleCode
{
/**
Interface for warriors.
*/
class IWarrior
{

protected:
/** The name of the warrior */
std::string _name;

/** The remaining life of the warrior */
int _life;

public:
/**
Constructor
@param name The name of the warrior.
@param life The initial life of the warrior.
*/
IWarrior(const std::string& name, int life): _name(name), _life(life) {}

/**
Attacks an opponent.
@param opponent The opponent to attack.
*/
virtual void Attack(IWarrior* opponent) const = 0;

/**
Takes damage from an opponents hit.
@param damage The damage to receive.
*/
virtual void TakeDamage(int damage) = 0;

/**
Accessor function for the name.
@post Does not change the object.
@return Name of the warrior.
*/
virtual std::string GetName() const = 0;

/**
Mutator function for the name.
@param newName The new name for the warrior.
*/
virtual void SetName(const std::string& newName) = 0;

/**
Accessor function for the alive property of the warrior.
@post Does not change the object.
@return True if alive.
*/
virtual bool IsAlive() const = 0;

/**
Empty deconstructor.
*/
virtual ~IWarrior() {}
};
}

#endif
Loading

0 comments on commit 53aa88a

Please sign in to comment.