Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Basic Examples #16

Merged
merged 6 commits into from
Jul 31, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,17 @@ include(CMakeModules/pch.cmake)
get_filename_component(AUTOWIRING_ROOT_DIR . ABSOLUTE)
if(CMAKE_SOURCE_DIR STREQUAL AUTOWIRING_ROOT_DIR)
set(AUTOWIRING_BUILD_TESTS_DEFAULT ON)
set(AUTOWIRING_BUILD_EXAMPLES_DEFAULT ON)
set(AUTOWIRING_BUILD_AUTONET_DEFAULT ON)

# All of our binaries go to one place: The binaries output directory. We only want to tinker
# with this if we're building by ourselves, otherwise we just do whatever the enclosing project
# wants us to do.
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
else()
set(AUTOWIRING_BUILD_TESTS_DEFAULT OFF)
set(AUTOWIRING_BUILD_EXAMPLES_DEFAULT OFF)
set(AUTOWIRING_BUILD_AUTONET_DEFAULT OFF)
endif()

option(AUTOWIRING_BUILD_TESTS "Build Autowiring unit tests" ${AUTOWIRING_BUILD_TESTS_DEFAULT})
Expand All @@ -53,7 +57,13 @@ include_directories(
)
add_subdirectory(src)
add_subdirectory(contrib)
# Build examples
option(AUTOWIRING_BUILD_EXAMPLES "Build Autowiring examples" ${AUTOWIRING_BUILD_EXAMPLES_DEFAULT})
if(AUTOWIRING_BUILD_EXAMPLES)
add_subdirectory(examples)
endif()

# CMake configurations
configure_file(autowiring-config.cmake.in autowiring-config.cmake @ONLY)
configure_file(autowiring-configVersion.cmake.in autowiring-configVersion.cmake @ONLY)

Expand Down
8 changes: 8 additions & 0 deletions examples/AutoFilterExample.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// Copyright (C) 2012-2014 Leap Motion, Inc. All rights reserved.
#include <autowiring/Autowired.h>
#include <iostream>
#include <memory>

int main() {
std::cout << "Hello World" << std::endl;
}
15 changes: 15 additions & 0 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
add_executable(ContextExample ContextExample.cpp)
target_link_libraries(ContextExample Autowiring)
set_property(TARGET ContextExample PROPERTY FOLDER "Examples")

add_executable(ThreadExample ThreadExample.cpp)
target_link_libraries(ThreadExample Autowiring)
set_property(TARGET ThreadExample PROPERTY FOLDER "Examples")

add_executable(EventExample EventExample.cpp)
target_link_libraries(EventExample Autowiring)
set_property(TARGET EventExample PROPERTY FOLDER "Examples")

add_executable(AutoFilterExample AutoFilterExample.cpp)
target_link_libraries(AutoFilterExample Autowiring)
set_property(TARGET AutoFilterExample PROPERTY FOLDER "Examples")
131 changes: 131 additions & 0 deletions examples/ContextExample.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
// Copyright (C) 2012-2014 Leap Motion, Inc. All rights reserved.
#include <autowiring/Autowired.h>
#include <iostream>
#include <memory>

// pretty print boolean with desciption
#define check(desc,val) std::cout << desc << (val ? ": True" : ": False") << std::endl

// dummy classes
class Foo {
public:
int x;
};

class Bar{
public:
Autowired<Foo> foo;
};

int main() {
///////////////////////////
// //
// GlobalCoreContext //
// //
///////////////////////////
{
// The CoreContext is the basic unit of organization in Autowriring. They are organized
// in a tree structure, the root of which is the GlobalCoreContext. Each thread
// keeps track of its current context, which defaults to GlobalCoreContext

// This creates a shared_ptr to the global context
AutoGlobalContext global;

// This is the a shared_ptr to the current context
AutoCurrentContext ctxt;

// Since we default to the current context, they should be the same
check("Current context is global", global==ctxt);
}

/////////////////////////////////////////////////
// //
// Context Creation and Switching Contexts //
// //
/////////////////////////////////////////////////
{
// New contexts can be created using the 'Create' factory method on a context.
// The factory will create a child context to 'this' context.
// A helper type 'AutoCreateContext' will call Create on the current context
// automatically

AutoGlobalContext global; //same as AutoCurrentContext here

// Create's a chile of the current context
AutoCreateContext childCtxt; // Same as childCtxt = AutoCurrentContext()->Create<void>();

// Even though we've created a child context, we're still in the global context
check("Are we in the GlobalCoreContext", AutoCurrentContext()->IsGlobalContext());

// CurrentContextPusher can be used to switch contexts using RAII patterns
{
CurrentContextPusher pshr(childCtxt);
check("Now in child context", AutoCurrentContext() == childCtxt);
}
// Back in global context
}

///////////////////////////////////////////////////////
// //
// Adding members to a context with AutoRequired //
// //
///////////////////////////////////////////////////////
{
// Switch to a child context
AutoCreateContext ctxt;
CurrentContextPusher pshr(ctxt);

// A single instance of any type can be injected into a context
// This is done using AutoRequied
AutoRequired<Foo> foo; // We now have a std::shared_ptr<Foo>

// AutoRequired will return an instance of the requested type from
// the current context. If that type doesn't exist in the current
// context, it will create an instace
foo->x = 5;

// If we try to AutoRequire a second Foo, we'll get a pointer to
// the same instance
AutoRequired<Foo> foo2;
check("foo2 is the same instance as foo", foo==foo2);
std::cout << "foo2 value of 'x': " << foo2->x << std::endl;

} // 'ctxt' and all members a destroyed when the context goes out of scope

//////////////////////
// //
// Autowired //
// //
//////////////////////
{
{
AutoCreateContext ctxt;
CurrentContextPusher pshr(ctxt);

// Autowired is similar to AutoRequied, except it doesn't create the
// object if it doesn't already exist. It also searches up the tree
// if the object isn't found in the current context
Autowired<Foo> foo;
check("foo is an empty pointer", !foo);

// If we inject to type Foo later, foo will automatically point to that instance
AutoRequired<Foo>();
check("foo now contains an instance of Foo", foo);
}

// This delayed satisfaction also works for class members.
{
AutoCreateContext ctxt;
CurrentContextPusher pshr(ctxt);

// Bar has an Autowrired<Foo> classmember
AutoRequired<Bar> bar;

check("Foo member of bar is satisfied before AutoRequired", bar->foo);

// If we inject Foo into the context, the Autowired<Foo> member of Bar will be satisfied
AutoRequired<Foo>();
check("Foo member of bar is satisfied after AutoRequired", bar->foo);
}
}
}
87 changes: 87 additions & 0 deletions examples/EventExample.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// Copyright (C) 2012-2014 Leap Motion, Inc. All rights reserved.
#include <autowiring/Autowired.h>
#include <iostream>
#include <memory>

/////////////////////////////////////////////////////////////////////
// //
// Autowiring Events //
// //
/////////////////////////////////////////////////////////////////////

// Autowiring events are just function calls on member functions in a context.
// All context members that implement function pointer you "fire" will be called

class MyEvent:
public EventReceiver
{
public:
virtual void myFunction(int) = 0;
};

// Will receive MyEvent::myFunction or FooEvent::myFunction events
class FooEvent:
public MyEvent
{
public:
FooEvent():
m_secret(0)
{}

void myFunction(int i) override {
m_secret = i;
}

int getSecret(){
return m_secret;
}
private:
int m_secret;
};

// Will receive MyEvent::myFunction or BarEvent::myFunction events
class BarEvent:
public MyEvent
{
public:
BarEvent():
m_secret(0)
{}

void myFunction(int i) override {
m_secret = i;
}

int getSecret(){
return m_secret;
}
private:
int m_secret;
};

int main(){
AutoCurrentContext ctxt;

// A context must be initiated before events can be received. Similar to CoreThread
ctxt->Initiate();

// This creates an proxy object that can fire MyEvent::* events
AutoFired<MyEvent> eventFirer;

// Inject receiver types into current context
AutoRequired<FooEvent> foo;
AutoRequired<BarEvent> bar;
std::cout << "Foo should be 0: " << foo->getSecret() << std::endl;
std::cout << "Bar Should be 0: " << bar->getSecret() << std::endl;

// Fire event, this should set m_secret on both foo and bar
eventFirer(&MyEvent::myFunction)(42);
std::cout << "Foo should be 42: " << foo->getSecret() << std::endl;
std::cout << "Bar should be 42: " << bar->getSecret() << std::endl;

// You can also manually fire events on a context with `Invoke`
// Since the function pointer is to `BarEvent`, `FooEvent` won't receive the event
//ctxt->Invoke(&BarEvent::myFunction)(77);
//std::cout << "Foo should be 42: " << foo->getSecret() << std::endl;
//std::cout << "Bar should be 77: " << bar->getSecret() << std::endl;
}
65 changes: 65 additions & 0 deletions examples/ThreadExample.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// Copyright (C) 2012-2014 Leap Motion, Inc. All rights reserved.
#include <autowiring/Autowired.h>
#include <autowiring/CoreThread.h>
#include <iostream>
#include <memory>
#include <thread>
#include <chrono>

class MyBasicThread:
public BasicThread
{
public:
virtual void Run() override {
for (auto x : {0, 1, 2 ,3}) {
std::cout << "MyBasicThread: " << x << "\n";
}
}
};

class MyCoreThread:
public CoreThread
{
public:
void AddToQueue(int x) {
*this += [x] {
std::cout << "MyCoreThread: " << x << "\n";
std::this_thread::sleep_for(std::chrono::milliseconds(500));
};
}
};

int main(){

// The 2 main thread classes in Autowiring are the BasicThread and CoreThread.
// Classes that inherit from these types will have thread capabilities
// Both start when their enclosing context is 'initiated'. Threads injected
// after the context is initiated will start immediatly

AutoRequired<MyBasicThread> myBasic;

AutoCurrentContext ctxt;
ctxt->Initiate(); // myBasic->Run() starts now in its own thread

std::this_thread::sleep_for(std::chrono::milliseconds(250));

std::cout << "injecting a CoreThread" << std::endl;

// Types inheriting from CoreThread implement a dispatch queue in their 'run()'
// function. Lambdas can be appended with operator+=

AutoRequired<MyCoreThread> myCore;
myCore->AddToQueue(42);
myCore->AddToQueue(1337);

*myCore += []{
std::cout << "This gets run after '1337'" << std::endl;
};

// This should be run before 'myCore' is finished
std::cout << "This thread is faster\n";

// This will wait for all outstanding threads to finish before terminating the context
ctxt->SignalShutdown(true);
}

5 changes: 5 additions & 0 deletions src/autonet/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ if(NOT Boost_FOUND)
return()
endif()

option(AUTOWIRING_BUILD_AUTONET "Build Autonet debugging server" ${AUTOWIRING_BUILD_AUTONET_DEFAULT})
if(NOT AUTOWIRING_BUILD_AUTONET)
return()
endif()

add_googletest(test)
include_directories(
${Boost_INCLUDE_DIR}
Expand Down