Skip to content

Commit

Permalink
Merge pull request #16 from leapmotion/feature-examples
Browse files Browse the repository at this point in the history
Basic Examples
  • Loading branch information
codemercenary committed Jul 31, 2014
2 parents 79ce603 + 0f28ca5 commit c9ff391
Show file tree
Hide file tree
Showing 7 changed files with 321 additions and 0 deletions.
10 changes: 10 additions & 0 deletions CMakeLists.txt
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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
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

0 comments on commit c9ff391

Please sign in to comment.