History

  • Who: Created by Douglas C. Schmidt at Washington University, St. Louis.
  • Why: To provide a portable, reusable C++ framework for building high-performance networked and real-time systems using well-known design patterns (Reactor, Proactor, Active Object).
  • When: Development started in the early 1990s. Widely used in telecom, defense, and financial systems.

Introduction

What is ACE?

  • An open-source C++ framework for building concurrent, networked, and real-time systems.
  • Implements classic concurrency and networking patterns: Reactor, Proactor, Active Object, Half-Sync/Half-Async.
  • Website: www.dre.vanderbilt.edu/~schmidt/ACE.html

Advantages

  • Battle-tested in mission-critical systems (telecom, defense, finance).
  • Implements well-known design patterns for concurrent programming.
  • Highly portable across OS and compilers.
  • Pairs with TAO for CORBA-based distributed systems.

Disadvantages

  • Very steep learning curve — complex API.
  • Large codebase with many abstractions.
  • Modern alternatives (Boost.Asio, POCO) are often simpler for new projects.
  • Documentation can be sparse for advanced features.

Installation & Setup

apt (Ubuntu)

sudo apt install libace-dev

Build from Source

git clone https://github.com/DOCGroup/ACE_TAO.git
cd ACE_TAO/ACE
# Set ACE_ROOT environment variable
export ACE_ROOT=$(pwd)
make

CMake

find_package(ACE REQUIRED)
target_link_libraries(MyApp ACE::ACE)

Core Concepts

TCP Echo Server (Reactor Pattern)

#include <ace/SOCK_Acceptor.h>
#include <ace/SOCK_Stream.h>
#include <ace/INET_Addr.h>
 
ACE_INET_Addr addr(5000);
ACE_SOCK_Acceptor acceptor(addr);
ACE_SOCK_Stream client;
 
acceptor.accept(client);
 
char buf[1024];
ssize_t n = client.recv(buf, sizeof(buf));
client.send(buf, n); // echo back
client.close();

TCP Client

#include <ace/SOCK_Connector.h>
#include <ace/SOCK_Stream.h>
#include <ace/INET_Addr.h>
 
ACE_INET_Addr server("localhost", 5000);
ACE_SOCK_Connector connector;
ACE_SOCK_Stream stream;
 
connector.connect(stream, server);
 
const char* msg = "Hello ACE!";
stream.send(msg, strlen(msg));
 
char buf[1024];
ssize_t n = stream.recv(buf, sizeof(buf));
buf[n] = '\0';
ACE_DEBUG((LM_INFO, "Received: %s\n", buf));
 
stream.close();

Threading (ACE_Thread_Manager)

#include <ace/Thread_Manager.h>
 
void* worker(void*) {
    ACE_DEBUG((LM_INFO, "Thread running\n"));
    return nullptr;
}
 
ACE_Thread_Manager::instance()->spawn(worker);
ACE_Thread_Manager::instance()->wait(); // wait for all threads

More Learn