100% found this document useful (8 votes)
59 views

The ACE programmer s guide practical design patterns for network and systems programming 5. print Edition Johnson 2024 scribd download

Johnson

Uploaded by

roiehuron
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
100% found this document useful (8 votes)
59 views

The ACE programmer s guide practical design patterns for network and systems programming 5. print Edition Johnson 2024 scribd download

Johnson

Uploaded by

roiehuron
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 85

Download the full version of the ebook at ebookfinal.

com

The ACE programmer s guide practical design


patterns for network and systems programming 5.
print Edition Johnson

https://ebookfinal.com/download/the-ace-programmer-s-guide-
practical-design-patterns-for-network-and-systems-
programming-5-print-edition-johnson/

OR CLICK BUTTON

DOWNLOAD EBOOK

Download more ebook instantly today at https://ebookfinal.com


Instant digital products (PDF, ePub, MOBI) available
Download now and explore formats that suit you...

Functional Programming in C Classic Programming Techniques


for Modern Projects Wrox Programmer to Programmer 1st
Edition Oliver Sturm
https://ebookfinal.com/download/functional-programming-in-c-classic-
programming-techniques-for-modern-projects-wrox-programmer-to-
programmer-1st-edition-oliver-sturm/
ebookfinal.com

Systems programmer s guide to z OS System Logger 1st ed


Edition Ibm Redbooks

https://ebookfinal.com/download/systems-programmer-s-guide-to-z-os-
system-logger-1st-ed-edition-ibm-redbooks/

ebookfinal.com

Websphere Studio Application Developer Version 5


Programming Guide Programming Guide 1st Edition Ibm
Redbooks
https://ebookfinal.com/download/websphere-studio-application-
developer-version-5-programming-guide-programming-guide-1st-edition-
ibm-redbooks/
ebookfinal.com

Therapist s Guide to Clinical Intervention Second Edition


The 1 2 3 s of Treatment Planning Practical Resources for
the Mental Health Professional Sharon L. Johnson
https://ebookfinal.com/download/therapist-s-guide-to-clinical-
intervention-second-edition-the-1-2-3-s-of-treatment-planning-
practical-resources-for-the-mental-health-professional-sharon-l-
johnson/
ebookfinal.com
The Theft of History 5. print Edition Jack Goody

https://ebookfinal.com/download/the-theft-of-history-5-print-edition-
jack-goody/

ebookfinal.com

Successful Marketing Communications A Practical Guide to


Planning and Implementation CIM Advanced Certificate
Workbook 1st Edition Cathy Ace
https://ebookfinal.com/download/successful-marketing-communications-a-
practical-guide-to-planning-and-implementation-cim-advanced-
certificate-workbook-1st-edition-cathy-ace/
ebookfinal.com

Professional Python Frameworks Web 2 0 Programming with


Django and Turbogears Programmer to Programmer 1st Edition
Moore
https://ebookfinal.com/download/professional-python-frameworks-
web-2-0-programming-with-django-and-turbogears-programmer-to-
programmer-1st-edition-moore/
ebookfinal.com

Practical Electrical Network Automation and Communication


Systems 1st Edition Cobus Strauss Cpeng Bsc (Eleceng)
Bcomm
https://ebookfinal.com/download/practical-electrical-network-
automation-and-communication-systems-1st-edition-cobus-strauss-cpeng-
bsc-eleceng-bcomm/
ebookfinal.com

MongoDB Applied Design Patterns Practical Use Cases with


the Leading NoSQL Database 1st Edition Rick Copeland

https://ebookfinal.com/download/mongodb-applied-design-patterns-
practical-use-cases-with-the-leading-nosql-database-1st-edition-rick-
copeland/
ebookfinal.com
The ACE Programmer’s Guide
This page intentionally left blank
The ACE Programmer’s Guide

Practical Design Patterns for Network and


Systems Programming

Stephen D. Huston
James CE Johnson
Umar Syyid

Boston • San Francisco • New York • Toronto • Montreal


London • Munich • Paris • Madrid
Capetown • Sydney • Tokyo • Singapore • Mexico City
Many of the designations used by manufacturers and sellers to distinguish their products are claimed as trademarks. Where those
designations appear in this book, and Addison-Wesley was aware of a trademark claim, the designations have been printed with
initial capital letters or all capitals.

The authors and publisher have taken care in the preparation of this book, but make no expressed or implied warranty of any kind
and assume no responsibility for errors or omissions. No liability is assumed for incidental or consequential damages in
connection with or arising out of the use of the information or programs contained herein.
Figures 7.1, 7.2, 7.3, and 8.1 originally published in Schmidt/Huston, C++ Network Programming, Volume 2: Systematic Reuse
with ACE and Frameworks, Copyright © 2003 by Pearson Education, Inc. Reprinted with permission of Pearson Education, Inc.
The publisher offers discounts on this book when ordered in quantity for bulk purchases and special sales. For more information,
please contact:
U.S. Corporate and Government Sales
(800) 382-3419
[email protected]
For sales outside of the U.S., please contact:
International Sales
[email protected]
Visit Addison-Wesley on the Web: www.awprofessional.com
Library of Congress Cataloging-in-Publication Data
Huston, Stephen D.
The ACE programmer’s guide : practical design patterns for network and systems
programming / Stephen D. Huston, James CE Johnson and Umar Syyid.
p. cm.
ISBN 0-201-69971-0 (pbk. : alk. paper)
1. Computer software—Development. 2. Object-oriented programming (Computer science)
3. Software patterns. I. Johnson, James C. E. II. Syyid, Umar. III. Title.
QA76.76.D47H89 2003
005.1’17—dc21 2003014046

Copyright © 2004 by Pearson Education, Inc.


All rights reserved. No part of this publication may be reproduced, stored in a retrieval system, or transmitted, in any form, or by
any means, electronic, mechanical, photocopying, recording, or otherwise, without the prior consent of the publisher. Printed in
the United States of America.
For information on obtaining permission for use of material from this work, please submit a written request to:
Pearson Education, Inc,
Rights and Contracts Department
75 Arlington Street, Suite 300
Boston, MA 02116
Fax: (617) 848-7047
ISBN13: 978-0-201-69975-5
ISBN 0-201-69971-0
Text printed in the United States at Offset Paperback Manufacturers in Laflin, Pennsylvania.
6th Printing March 2010
Contents

Illustrations. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xi
Tables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xiii
Foreword . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xv
Preface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xix
Part I: ACE Basics 1
1. Introduction to ACE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.1 A History of ACE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.2 ACE’s Benefits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.3 ACE’s Organization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.4 Patterns, Class Libraries, and Frameworks. . . . . . . . . . . . . . . . . . . . . . . 7
1.5 Porting Your Code to Multiple Operating Systems . . . . . . . . . . . . . . . . 8
1.6 Smoothing the Differences among C++ Compilers . . . . . . . . . . . . . . . 11
1.7 Using Both Narrow and Wide Characters . . . . . . . . . . . . . . . . . . . . . . 19
1.8 Where to Find More Information and Support. . . . . . . . . . . . . . . . . . . 21
1.9 Summary. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
2. How to Build and Use ACE in Your Programs . . . . . . . . . . . . . . . 25
2.1 A Note about ACE Versions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
2.2 Guide to the ACE Distribution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26

v
vi Contents

2.3 How to Build ACE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27


2.4 How to Include ACE in Your Applications . . . . . . . . . . . . . . . . . . . . . 30
2.5 How to Build Your Applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
2.6 Summary. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
3. Using the ACE Logging Facility . . . . . . . . . . . . . . . . . . . . . . . . . . 37
3.1 Basic Logging and Tracing. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
3.2 Enabling and Disabling Logging Severities . . . . . . . . . . . . . . . . . . . . . 43
3.3 Customizing the ACE Logging Macros . . . . . . . . . . . . . . . . . . . . . . . . 47
3.4 Redirecting Logging Output . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
3.5 Using Callbacks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
3.6 The Logging Client and Server Daemons . . . . . . . . . . . . . . . . . . . . . . 64
3.7 The LogManager Class. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
3.8 Runtime Configuration with the ACE Logging Strategy . . . . . . . . . . . 73
3.9 Summary. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
4. Collecting Runtime Information . . . . . . . . . . . . . . . . . . . . . . . . . . 77
4.1 Command Line Arguments and ACE_Get_Opt . . . . . . . . . . . . . . . . . . 78
4.2 Accessing Configuration Information . . . . . . . . . . . . . . . . . . . . . . . . . 83
4.3 Building Argument Vectors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
4.4 Summary. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
5. ACE Containers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
5.1 Container Concepts. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
5.2 Sequence Containers. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
5.3 Associative Containers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
5.4 Allocators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115
5.5 Summary. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119

Part II: Interprocess Communication 121


6. Basic TCP/IP Socket Use . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123
6.1 A Simple Client . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
6.2 Adding Robustness to a Client . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129
6.3 Building a Server . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135
6.4 Summary. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140
7. Handling Events and Multiple I/O Streams . . . . . . . . . . . . . . . . . 141
7.1 Overview of the Reactor Framework . . . . . . . . . . . . . . . . . . . . . . . . . 142
7.2 Handling Multiple I/O Sources. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142
Contents vii

7.3 Signals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155


7.4 Notifications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158
7.5 Timers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160
7.6 Using the Acceptor-Connector Framework . . . . . . . . . . . . . . . . . . . . 168
7.7 Reactor Implementations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181
7.8 Summary. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185
8. Asynchronous I/O and the ACE Proactor Framework . . . . . . . . . 187
8.1 Why Use Asynchronous I/O? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 188
8.2 How to Send and Receive Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 189
8.3 Establishing Connections . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197
8.4 The ACE_Proactor Completion Demultiplexer . . . . . . . . . . . . . . . . . 201
8.5 Using Timers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 202
8.6 Other I/O Factory Classes. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 202
8.7 Combining the Reactor and Proactor Frameworks. . . . . . . . . . . . . . . 203
8.8 Summary. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 205
9. Other IPC Types. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207
9.1 Interhost IPC with UDP/IP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207
9.2 Intrahost Communication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 213
9.3 Summary. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 215

Part III: Process and Thread Management 217


10. Process Management . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 219
10.1 Spawning a New Process . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 219
10.2 Using the ACE_Process_Manager . . . . . . . . . . . . . . . . . . . . . . . . . . . 226
10.3 Synchronization Using ACE_Process_Mutex . . . . . . . . . . . . . . . . . . 231
10.4 Summary. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 234
11. Signals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 235
11.1 Using Wrappers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 236
11.2 Event Handlers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 239
11.3 Guarding Critical Sections . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 246
11.4 Signal Management with the Reactor. . . . . . . . . . . . . . . . . . . . . . . . . 247
11.5 Summary. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 248
12. Basic Multithreaded Programming . . . . . . . . . . . . . . . . . . . . . . 249
12.1 Getting Started . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 250
12.2 Basic Thread Safety . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 251
viii Contents

12.3 Intertask Communication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 257


12.4 Summary. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 266
13. Thread Management. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 267
13.1 Types of Threads. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 267
13.2 Priorities and Scheduling Classes. . . . . . . . . . . . . . . . . . . . . . . . . . . . 271
13.3 Thread Pools . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 275
13.4 Thread Management Using ACE_Thread_Manager . . . . . . . . . . . . . 276
13.5 Signals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 279
13.6 Thread Start-Up Hooks. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 283
13.7 Cancellation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 284
13.8 Summary. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 288
14. Thread Safety and Synchronization . . . . . . . . . . . . . . . . . . . . . . 289
14.1 Protection Primitives . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 289
14.2 Thread Synchronization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 301
14.3 Thread-Specific Storage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 309
14.4 Summary. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 311
15. Active Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 313
15.1 The Pattern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 314
15.2 Using the Pattern. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 316
15.3 Summary. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 324
16. Thread Pools. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 325
16.1 Understanding Thread Pools . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 325
16.2 Half-Sync/Half-Async Model. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 326
16.3 Leader/Followers Model. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 338
16.4 Thread Pools and the Reactor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 343
16.5 Summary. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 346

Part IV: Advanced ACE 347


17. Shared Memory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 349
17.1 ACE_Malloc and ACE_Allocator . . . . . . . . . . . . . . . . . . . . . . . . . . . 350
17.2 Persistence with ACE_Malloc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 352
17.3 Position-Independent Allocation . . . . . . . . . . . . . . . . . . . . . . . . . . . . 356
17.4 ACE_Malloc for Containers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 359
17.5 Wrappers. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 374
17.6 Summary. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 376
Contents ix

18. ACE Streams Framework. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 377


18.1 Overview. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 377
18.2 Using a One-Way Stream . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 378
18.3 A Bidirectional Stream . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 397
18.4 Summary. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 417
19. ACE Service Configurator Framework . . . . . . . . . . . . . . . . . . . 419
19.1 Overview. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 420
19.2 Configuring Static Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 420
19.3 Setting Up Dynamic Services. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 427
19.4 Setting Up Streams . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 430
19.5 Reconfiguring Services During Execution . . . . . . . . . . . . . . . . . . . . . 431
19.6 Using XML to Configure Services and Streams . . . . . . . . . . . . . . . . 433
19.7 Configuring Services without svc.conf. . . . . . . . . . . . . . . . . . . . . . . . 434
19.8 Singletons and Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 434
19.9 Summary. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 435
20. Timers. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 437
20.1 Timer Concepts. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 437
20.2 Timer Queues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 439
20.3 Prebuilt Dispatchers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 447
20.4 Managing Event Handlers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 450
20.5 Summary. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 455
21. ACE Naming Service . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 457
21.1 The ACE_Naming_Context . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 457
21.2 A Single-Process Naming Context: PROC_LOCAL . . . . . . . . . . . . . 459
21.3 Sharing a Naming Context on One Node: NODE_LOCAL. . . . . . . . 468
21.4 Sharing a Naming Context across the Network: NET_LOCAL . . . . 476
21.5 Summary. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 478
Bibliography . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 479
Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 481
This page intentionally left blank
Illustrations

7.1 Acceptor-Connector framework classes . . . . . . . . . . . . . . . . . . . . . . . 169


7.2 Steps in ACE_Acceptor connection acceptance. . . . . . . . . . . . . . . 172
7.3 Reactive shutdown of an ACE_Svc_Handler . . . . . . . . . . . . . . . . 176
8.1 Classes in the Proactor framework . . . . . . . . . . . . . . . . . . . . . . . . . . . 190
8.2 Sequence diagram for asynchronous data echo example . . . . . . . . . . 196
12.1 Using a queue for communication . . . . . . . . . . . . . . . . . . . . . . . . . . . 261
13.1 Kernel- and User-Level Threads. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 269
15.1 Asynchronous log() method . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 314
15.2 Active Object pattern participants . . . . . . . . . . . . . . . . . . . . . . . . . . . 315
15.3 Active Object collaborations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 317
15.4 Active Object pattern applied to example. . . . . . . . . . . . . . . . . . . . . . 319
18.1 Diagram of an ACE_Stream . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 379
18.2 Logical structure of the command stream . . . . . . . . . . . . . . . . . . . . . 397
20.1 Timer queue class hierarchy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 438
20.2 Timer dispatcher example class diagram . . . . . . . . . . . . . . . . . . . . . . 441
20.3 Timer dispatcher example sequence diagram . . . . . . . . . . . . . . . . . . . 442
20.4 Timer queue template classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 451
20.5 Upcall handler sequence diagram. . . . . . . . . . . . . . . . . . . . . . . . . . . . 452

xi
This page intentionally left blank
Tables

1.1 Data Types Defined by ACE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15


1.2 ACE Memory Allocation Macros. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
1.3 Macros Related to Character Width . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
2.1 Configuration Files for Popular ACE Platforms . . . . . . . . . . . . . . . . . 29
2.2 GNU make Options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
2.3 ACE Library File Names for Visual C++. . . . . . . . . . . . . . . . . . . . . . . 35
3.1 ACE_Log_Msg Logging Severity Levels . . . . . . . . . . . . . . . . . . . . . . 39
3.2 ACE Logging Format Directives . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
3.3 ACE Logging Macros. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
3.4 Commonly Used ACE_Log_Msg Methods. . . . . . . . . . . . . . . . . . . . . 48
3.5 Valid ACE_Log_Msg Flags Values . . . . . . . . . . . . . . . . . . . . . . . . . . 56
3.6 Mapping ACE Logging Severity to Windows Event Log Severity . . . 58
3.7 ACE_Log_Record Attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
3.8 ACE Logging Strategy Configuration Options . . . . . . . . . . . . . . . . . . 75
5.1 Allocators Available in ACE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116
7.1 Meaning of Event Handler Callback Return Values . . . . . . . . . . . . . 149
12.1 ACE Guard Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 256
12.2 Various Queue Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 266

xiii
xiv Tables

13.1 Thread Creation Flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 268


13.2 Thread Priority Macros. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 272
14.1 Protection Primitives in ACE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 290
14.2 ACE Synchronization Primitives . . . . . . . . . . . . . . . . . . . . . . . . . . . . 302
17.1 Memory Pool Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 351
17.2 Memory Pool Macro Names. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 352
17.3 ACE_MMAP_Memory_Pool_Options Attributes . . . . . . . . . . . . 360
19.1 Service Configurator Command Line Options. . . . . . . . . . . . . . . . . . 427
20.1 Timer Storage Structures and Relative Performance . . . . . . . . . . . . . 439
21.1 Name Options Attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 458
Foreword

I started programming computers in the mid-1980s. Then, like today, computing


and communication systems were heterogeneous; that is, there were many
different programming languages, operating systems, and networking protocols.
Moreover, due to the accidental complexities of programming with low-level and
nonportable application programming interfaces (APIs), the types of networked
applications available to software developers and end users were relatively primi-
tive, consisting largely of e-mail, remote login, and file transfer. As a result, many
applications were either centralized on mainframes and minicomputers or local-
ized on a single stand-alone PC or workstation.
There have been significant advances in information technology (IT) for
computing and communication during the intervening two decades. Languages,
programming environments, operating systems, networking protocols, and
middleware are more mature and standardized. For example, C++ has become an
ISO/ANSI standard and is being used in a broad range of application domains.
Likewise, the UNIX, Windows, and TCP/IP standards have also become ubiqui-
tous. Even distributed computing middleware standards, such as CORBA, .NET,
and J2EE, are becoming widely embraced by the IT industry and end users.
Even with all these advances, however, there is still a layer of the networked
software design space—host infrastructure middleware for performance-driven,
multiplatform, networked and/or concurrent software systems—that is not well
served by standard solutions at other levels of abstraction. Host infrastructure
middleware encapsulates native operating system (OS) concurrency and interpro-
xv
xvi Foreword

cess communication (IPC) mechanisms to alleviate many tedious, error-prone,


and nonportable activities associated with developing networked applications via
native OS APIs, such as Sockets or POSIX threads (Pthreads). Performance-
driven systems also have stringent quality of service (QoS) requirements.
Providing host infrastructure middleware for today’s popular computing envi-
ronments is particularly important for (1) high-performance computing systems,
such as those that support scientific visualization, distributed database servers, and
online financial trading systems; (2) distributed real-time and embedded systems
that monitor and control real-world artifacts, such as avionics mission- and flight-
control software, supervisory control and data acquisition systems, and automo-
tive braking systems; and (3) multiplatform applications that must run portably
across local- and wide-area networks. These types of systems are increasingly
subject to the following trends:
• The need to access native OS mechanisms to meet QoS requirements. For
example, multimedia applications that require long-duration, bidirectional
bytestream communication services are poorly suited to the synchronous
request/response model provided by conventional distribution middleware.
Likewise, many distribution middleware implementations incur significant
overhead and lack sufficient hooks to manipulate other QoS-related proper-
ties, such as latency, throughput, and jitter.
• Severe cost and time-to-market pressures. Global competition and market
deregulation are shrinking budgets for the in-house development and quality
assurance (QA) of software, particularly for the OS and middleware infra-
structure. Moreover, performance-driven users are often unable or less willing
to pay for specialized proprietary infrastructure software.
• The demand for user-specific customization. Because performance-intensive
software often pushes the limits of technology, it must be optimized for partic-
ular runtime contexts and application requirements. General-purpose, one-
size-fits-all software solutions often have unacceptable performance.
As these trends continue to accelerate, they present many challenges to developers
of tomorrow’s networked software systems. In particular, to succeed in today’s
competitive, fast-paced computing industry, successful middleware and applica-
tion software must exhibit the following eight characteristics:
1. Affordability, to ensure that the total ownership costs of software acquisition
and evolution aren’t prohibitively high
2. Extensibility, to support successions of quick updates and additions to address
new requirements and take advantage of emerging markets
Foreword xvii

3. Flexibility, to support a growing range of data types, traffic flows, and end-to-
end QoS requirements
4. Portability, to reduce the effort required to support applications on heteroge-
neous OS platforms and compilers
5. Predictability and efficiency, to provide low latency to delay-sensitive real-
time applications, high performance to bandwidth-intensive applications, and
usability over low-bandwidth networks, such as wireless links
6. Reliability, to ensure that applications are robust and tolerant of faults
7. Scalability, to enable applications to handle many users simultaneously
8. Trustworthiness, to ensure integrity, confidentiality, and availability in inter-
networked systems
I’ve encountered all these challenges while working on scores of research and
production performance-driven software systems during the past two decades. In
1992, I began creating a software toolkit called the ADAPTIVE Communication
Environment (ACE) to address concurrent network programming challenges.
ACE is portable object-oriented host infrastructure middleware written in C++.
ACE was designed to solve a very pragmatic problem—to save time imple-
menting my doctoral dissertation project on parallel protocol processing engines
in both SunOS 4.x and SunOS 5.x operating systems. Having worked on free soft-
ware projects for many years, I recognized immediately that making ACE avail-
able in open-source form would help to galvanize a community whereby other
developers and users could assist with the QA, documentation, and support activi-
ties needed to transform ACE into a high-quality production software toolkit.
Over the next decade, a core group of around 30 developers and I teamed up
with more than 1,700 contributors from around the world to evolve ACE so it
encapsulates and augments a wide range of native OS capabilities that are essen-
tial to support performance-driven software systems. The core frameworks and
wrapper facades in ACE provide an integrated collection of reusable object-
oriented classes that simplify and automate connection establishment, event
demultiplexing, secure and efficient interprocess communication, (de)marshaling,
dynamic configuration of application components, concurrency, and synchroniza-
tion. Most important, the ACE frameworks can be customized readily to support a
wide range of runtime contexts and application requirements.
Today‚ ACE runs on dozens of hardware and OS platforms, including most
versions of Windows and UNIX, as well as many real-time and embedded oper-
ating systems. Due to its maturity, efficiency, and scope, ACE is being used by
thousands of development teams, ranging from large Fortune 500 companies to
xviii Foreword

small start-ups to advanced research projects at universities and industry labs. Its
open-source development model and highly knowledgeable user community is
similar in spirit, enthusiasm, and productivity to that driving the Linux operating
system, the Apache web server, and the GNU compiler collection.
For many years, however, the only way to learn ACE was to read the source
code and example applications, technical papers that described its patterns and the
design of its frameworks, and online tutorials. Although a surprisingly large
number of ACE users managed to master ACE via this process, the learning curve
was time consuming and error prone. In 2002 and 2003, I teamed up with Steve
Huston to write a pair of books on C++ Network Programming (C++NP), which
cover the motivation, design, implementation, and use of the most popular
wrapper facade classes and frameworks in ACE.
The ACE Programmer’s Guide takes a different tack from the C++NP books,
explaining quickly and directly how to make the best use of ACE. In addition to its
nuts-and-bolts approach to explaining key ACE capabilities, this book addresses
important topics not covered in the C++NP books, including how to build ACE
and your programs that use ACE, ACE’s OS and compiler portability features, the
ACE logging facility, command line options processing, container classes, signal
handling, and shared memory. The book also covers certain material in greater
depth than the C++NP books, including concurrency models, bidirectional
streams, and asynchronous I/O. Throughout this book, many examples using ACE
show how key patterns and design principles can be applied to develop object-
oriented networked software successfully. By learning the material in this book‚
you’ll be better able to design and implement performance-driven networked soft-
ware that can’t be bought off-the-shelf, thereby staying ahead of your competition.
We are fortunate that Steve, James, and Umar have found time in their hectic
schedules to write this book. If you’re designing software and systems that must
be portable, flexible, extensible, predictable, reliable, and affordable, this book
and the ACE toolkit will enable you to be more effective in all these areas. Even
after spending more than a decade developing ACE and using it to build
networked software applications, I find that I’ve learned a great deal from this
book‚ and I’m confident that you will too.

—Douglas C. Schmidt
Professor of Electrical Engineering and Computer Science at
Vanderbilt University and Inventor of ACE
Nashville, Tennessee
Preface

ACE (the ADAPTIVE Communication Environment) is a powerful C++ toolkit


that helps you develop portable, high-performance applications, especially
networked and/or multithreaded applications, more easily and more quickly with
more flexibility and fewer errors. And, because of ACE’s design and frameworks,
you can do all this with much less code than with other development approaches.
We’ve been using ACE for years and have found it exceedingly helpful and well
worth any price. What’s better is that it’s available for free! The historical price
many developers have paid to use ACE is a steep learning curve. It’s a big toolkit
with a large set of capabilities. Until recently, the best documentation has been the
source code, which is, of course, freely available, and a set of academic papers
born of the research that produced ACE, approachable only by advanced profes-
sionals and upper-level students. This barrier to learning has kept ACE’s power
and easy-to-use elegance one of the best-kept secrets in software development.
That’s why we’re very excited to write this book! It flattens out ACE’s learning
curve, bringing ACE’s power, elegance, and capabilities to all.
This book teaches you about ACE: a bit of its history and approach to develop-
ment, how it’s organized, how to begin using it, and also how to use some of its
more advanced capabilities. We teach you how to do things the ACE way in this
book, but we could not possibly fit in a complete reference. Use this book to get
started with ACE and to begin using it in your work. If you’ve been using ACE for
a while, there are probably descriptions of some capabilities you haven’t seen
before, so the book is useful for experienced ACE users as well.
xix
xx Preface

Who Should Read This Book


This book is meant to serve as both an introductory guide for ACE beginners and
a quickly accessible review for experienced ACE users. If you are an ACE
beginner, we recommend starting at the beginning and proceeding through the
chapters in order. If you are experienced and know what you want to read about,
you can quickly find that part of the book and do not need to read the previous
sections.
This book is written for C++ programmers who have been exposed to some of
the more advanced C++ features, such as virtual inheritance and class templates.
You should also have been exposed to basic operating system facilities you plan to
use in your work. For example, if you plan to write programs that use TCP/IP
sockets, you should at least be familiar with the general way sockets are created,
connections are established, and data is transferred.
This book is also an excellent source of material for those who teach others: in
either a commercial or an academic setting. ACE is an excellent example of how
to design object-oriented software and use C++ to design and write high-perfor-
mance, easily maintained software systems.

Organization
This book is a hands-on, how-to guide to using ACE effectively. The many source
code examples illustrate proper use of the pieces of ACE being described. The
source code examples are kept fairly short and to the point. Sometimes, the
example source is abridged in order to focus attention on a topic. The complete
source code to all examples is on the included CD-ROM and is also available on
Riverace Corporation’s web site. The included CD-ROM also includes a copy of
ACE’s source kit, installable versions of ACE prebuilt for a number of popular
platforms, and complete reference documentation for all the classes in ACE.
The book begins with basic areas of functionality that many ACE users need
and then proceeds to build on the foundations, describing the higher-level features
that abstract behavior out into powerful patterns.
• Part I introduces ACE and provides some generally useful information about
the facilities ACE provides. Part I also explains how to configure and build
ACE, as well as how to build your applications that use ACE. Widely used
programming aids, such as logging and tracing, command line processing and
configuration access, and ACE’s container classes, are also described.
Preface xxi

• Part II discusses ACE’s facilities for interprocess communication (IPC),


beginning with basic, low-level TCP/IP Sockets wrapper classes and
proceeding to show how to handle multiple sockets, as well as other events,
such as timers and signals, simultaneously using ACE’s Reactor and Proactor
frameworks. Part II also describes ACE’s Acceptor-Connector framework and
then ends with a discussion of some of the other IPC wrapper classes ACE
offers, many of which are substitutable for TCP/IP wrapper classes in the
covered frameworks.
• Part III covers a wide range of topics related to process and thread manage-
ment using ACE. This part explains how to use ACE’s process management
classes and then covers signals, followed by three chapters about multi-
threaded programming, thread management, and the critical areas of thread
safety and synchronization. Part III ends with discussions of Active Objects
and various ways to use thread pools in ACE—critical topics for effective use
of multithreading in high-performance applications.
• Part IV covers advanced ACE topics: shared memory, the ACE Streams
framework for assembling modular data-processing streams, and how to make
your applications more flexible and configurable by using the ACE Service
Configurator framework. Part IV concludes with an in-depth discussion of
ACE’s timer management classes and the ACE Naming Service, one of
ACE’s network services components to assist with often needed networked
application programming tasks.
The book concludes with a bibliography and an extensive subject index.

Conventions Used in This Book


All ACE classes begin with ACE_. When we refer to patterns instead of the
classes they implement, we omit the prefix. For example, the Reactor pattern is
implemented by the ACE_Reactor class.
All class member variables are suffixed with ‘_’. This convention is used in
the ACE sources, and we carry it through to the examples in this book as well.
C++ code and file names are set in this font. Command lines are set in
this font.
xxii Preface

Acknowledgments
We are indebted to the review team that read and commented on the entire manu-
script. Craig L. Ching, Dave Mercer, Johnny Willemsen, and Steven P. Witten
provided insightful and helpful feedback and ideas that improved the book greatly.
We are also grateful to the members of the ACE user community worldwide
who volunteered their free time to review a number of manuscript drafts and
provide helpful corrections and advice. Like the many contributors to ACE itself,
these individuals show the cooperative nature of many Open-Source developer/
user communities, and the ACE users in particular: Bill Cassanova, Ufuk Çoban,
Kobi Cohen-Arazi, Todd Cooper, Ning Cui, Alain Decamps, John Fowler, Chris
D. Gill, Andy Harvey, Dale Hawkins, Kelly F. Hickel, Don Hinton, Bill Hopkins,
Robert Kindred, Michael Kleck, Franz Klein, Sven Köster, Dieter Knüppel, Theo
Landman, Mark Levan, Alexander Libman, John Lilley, Stephen McDonald, Mike
Mullen, Mats Nilsson, Jaroslaw Nozderko, Rick Ohnemus, Wojtek Pilorz,
Sunanda C. Prasad, Dietrich Quehl, Irma Rastegayeva, Karen Regner, Michael
Searles, Rich Siebel, Chris Smith, Scott Smith, Edward Thompson, Alain
Totouom, Bill Trudell, and Lothar Werzinger.
Our editorial team at Addison-Wesley was very helpful and encouraging
during this long process as well. Thanks to our editors: Marina Lang, Debbie
Lafferty, Peter Gordon, and Bernie Gaffney. Thank you to our copy editor, Evelyn
Pyle, who did a marvelous job molding our differing approaches and styles into a
unified whole. Many, many thanks to our production coordinator, Elizabeth Ryan,
who has now ushered all three ACE-related books through production with great
skill, grace, and patience.

Steve’s Acknowledgments
As in all my work, I am deeply indebted to my wonderful wife, Jane, for her
abiding love, constant support, and much-needed help during the long process of
writing this book. You sacrificed much more than anyone should ever have to and
are truly God’s gift to me—thank you! As wise Solomon once said, “Of making
many books there is no end, and much study wearies the body” (Ecclesiastes
12:12, NIV). I’m a bit weary and thankful to God for the energy to complete this
work. I’m also grateful to my late mother, Karen L. Anderson, who would be
pleased with the lessons I’ve finally learned.
Preface xxiii

James’s Acknowledgments
I would like to thank my wife, Karla, and my son, Riley, who was born half-way
through this four-year process, for their patience and understanding every time I
disappeared into the basement office for hours on end. Without their constant
support and encouragement, I don’t think I would have ever made it to this point. I
would also like to thank my parents for always encouraging me to put forth my
best effort and to never settle for second best. And, finally, thanks to Doug
Schmidt for creating ACE in the first place and giving us all the opportunity to
create this text.

Umar’s Acknowledgments
First of all I would like to thank my wife, Ambreen, and my son, Hassan. If it
weren’t for them, I might not leave the computer at all for a few days; thanks for
calling me home. Ambreen deserves my special thanks for enduring my constant
babble over the years. Without her support, I would not have written a single page.
I would also like to thank my mother for her courage and support during the more
difficult times in my life. In addition, I would like to thank my father for making
me want to show him that I could. Finally, thanks to Doug Schmidt for driving
down to the University of Illinois to provide a graduate seminar that first taught
me about a framework called ACE.

Concluding Remarks
This book is a true coauthorship, with each of us writing equal amounts of the
text. Therefore, we all share equally in the blame for any problems you may find
in the text. Please report anything you do find to either the ACE users mailing list
([email protected]) or to us at [email protected].
Writing a book on a topic as broad as ACE is a very difficult task. The fact that we
had a team of authors made the task considerably easier. In addition, the help
available from the DOC group and the ACE user community has proved invalu-
able.

Steve Huston
James CE Johnson
Umar Syyid
This page intentionally left blank
Part I

ACE Basics
This page intentionally left blank
Chapter 1
Introduction to ACE

ACE is a rich and powerful toolkit with a distinctively nontraditional history. To


help you get a feel for where ACE comes from, this chapter gives a brief history of
ACE’s development. Before going into programming details, we cover some foun-
dational concepts: class libraries, patterns, and frameworks. Then we cover one of
ACE’s less glamorous but equally useful aspects: its facilities for smoothing out
the differences among operating systems, hardware architectures, C++ compilers,
and C++ runtime support environments. It is important to understand these aspects
of ACE before we dive into the rest of ACE’s capabilities.

1.1 A History of ACE


ACE (the ADAPTIVE—A Dynamically Assembled Protocol Transformation,
Integration, and eValuation Environment—Communication Environment) grew
out of the research and development activities of Dr. Douglas C. Schmidt at the
University of California at Irvine. Doug’s work was focused on design patterns,
implementation, and experimental analysis of object-oriented techniques that
facilitate the development of high-performance, real-time distributed object
computing frameworks. As is so often the case, that work began on a small
handful of hardware and OS (operating system) platforms and expanded over
time. Doug ran into the following problems that still vex developers today.

3
4 Chapter 1: Introduction to ACE

• Trying to rearrange code to try out new combinations of processes, threads,


and communications mechanisms is very tedious. The process of ripping code
apart, rearranging it, and getting it working again is very boring and error
prone.
• Working at the OS API (application programming interface) level adds acci-
dental complexity. Identifying the subtle programming quirks and resolving
these issues takes an inordinate amount of time in development schedules.
• Successful projects need to be ported to new platforms and platform versions.
Standards notwithstanding, no two platforms or versions are the same, and the
complexities begin again.
Doug, being the smart guy he is, came up with a plan. He invented a set of
C++ classes that worked together, allowing him to create templates and strategize
his way around the bumps inherent in rearranging the pieces of his programs.
Moreover, these classes implemented some very useful design patterns for
isolating the changes in the various computing platforms he kept getting, making
it easy for his programs to run on all the new systems his advisors and colleagues
could throw at him. Life was good. And thus was born ACE.
At this point, Doug could have grabbed his Ph.D. and some venture funding
and taken the world of class libraries by storm. We’d all be paying serious money
for the use of ACE today. Fortunately for the world’s C++ developers, Doug
decided to pursue further research in this area. He created the large and successful
Distributed Object Computing group at Washington University in St. Louis. ACE
was released as Open Source,1 and its development continued with the aid of more
than US$7 million funding from visionary commercial sponsors.
Today, most of the research-related work on ACE is carried out at the Institute
for Software Integrated Systems (ISIS) at Vanderbilt University, where Doug is
now a professor and still heavily involved in ACE’s day-to-day development. ACE
is increasingly popular in commercial development as well. It enjoys a reputation
for solving the cross-platform issues that face all high-performance networked
application and systems developers. Additionally, commercial-level technical
support for ACE is now available worldwide.
ACE is freely available for any use, including commercial, without onerous
licensing requirements. For complete details, see the COPYING file in the top-
level directory of the ACE source kit. Another interesting file in the top-level

1. If you’d like more information on Open Source Software in general, please visit the Open Source
Initiative page on the web at http://www.opensource.org/.
1.2 ACE’s Benefits 5

directory is THANKS. It lists all the people who have contributed to ACE over the
years—more than 1,700 at the time of this writing! If you contribute improve-
ments or additions to ACE, you too can get your name listed.

1.2 ACE’s Benefits


The accidental complexity and development issues that led to ACE reflect lessons
learned by all of us who’ve written networking programs, especially portable,
high-performance networking programs.
• Multiplatform source code is difficult to write. The many and varied standards
notwithstanding, each new port introduces a new set of problems. To remain
flexible and adaptive to new technology and business conditions, software
must be able to quickly change to take advantage of new operating systems
and hardware. One of the best ways to remain that flexible is to take advantage
of libraries and middleware that absorb the differences for you, allowing your
code to remain above the fray. ACE has been ported to a wide range of
systems—from handheld to supercomputer—running a variety of operating
systems and using many of the available C++ compilers.
• Networked applications are difficult to write. Introducing a network into your
design introduces a large set of challenges and issues throughout the develop-
ment process. Network latency, byte ordering, data structure layout, network
instability and performance, and handling multiple connections smoothly are a
few typical problems that you must be concerned with when developing
networked applications. ACE makes dozens of frameworks and design pattern
implementations available to you, so you can take advantage of solutions that
many other smart people have already come up with.
• Most system-provided APIs are written in terms of C API bindings because C
is so common and the API is usable from a variety of languages. If you’re
considering working with ACE, you’ve already committed to using C++,
though, and the little tricks that seemed so slick with C, such as overlaying the
sockaddr structure with sockaddr_in, sockaddr_un, and friends, are
just big opportunities for errors. Low-level APIs have many subtle require-
ments, which sometimes change from standard to standard—as in the series of
drafts leading to POSIX 1004.1c Pthreads—and are sometimes poorly docu-
mented and difficult to use. (Remember when you first figured out that the
socket(), bind(), listen(), and accept() functions were all
6 Chapter 1: Introduction to ACE

related?) ACE provides a well-organized, coherent set of abstractions to make


IPC, shared memory, threads, synchronization mechanisms, and more easy to
use.

1.3 ACE’s Organization


ACE is more than a class library. It is a powerful, object-oriented application
toolkit. Although it is not apparent from a quick look at the source or reference
pages, the ACE toolkit is designed using a layered architecture composed of the
following layers:
• OS adaptation layer. The OS adaptation layer provides wrapper functions for
most common system-level operations. This layer provides a common base of
system functions across all the platforms ACE has been ported to. Where the
native platform does not provide a desired function, it is emulated, if possible.
If the function is available natively, the calls are usually inlined to maximize
performance.
• Wrapper facade layer. A wrapper facade consists of one or more classes that
encapsulate functions and data within a type-safe, object-oriented
interface [5]. ACE’s wrapper facade layer makes up nearly half of its source
base. This layer provides much of the same capability available natively and
via the OS adaptation layer but in an easier-to-use, type-safe form. Applica-
tions make use of the wrapper facade classes by selectively inheriting, aggre-
gating, and/or instantiating them.
• Framework layer. A framework is an integrated collection of components that
collaborate to produce a reusable architecture for a family of related
applications [4] [7]. Frameworks emphasize the integration and collaboration
of application-specific and application-independent components. By doing
this, frameworks enable larger-scale reuse of software rather than simply
reusing individual classes or stand-alone functions. ACE’s frameworks inte-
grate wrapper facade classes and implement canonical control flows and class
collaborations to provide semicomplete applications. It is very easy to build
applications by supplying application-specific behavior to a framework.
• Networked services layer. The networked services layer provides some
complete, reusable services, including the distributed logging service we’ll see
in Chapter 3.
1.4 Patterns, Class Libraries, and Frameworks 7

Each layer reuses classes in lower layers, abstracting out more common func-
tionality. This means that any given task in ACE can usually be done in more than
one way, depending on your needs and design constraints. Although we some-
times approach a problem “bottom up” because existing knowledge helps transi-
tion smoothly to ACE programming techniques, we generally cover the higher-
level ways rather than the lower-level ways to approach problems in more depth. It
is relatively easy, however, to find the lower-level classes and interfaces for your
use when needed. The ACE reference documentation on the included CD-ROM
can be used to find all class relationships and complete programming references.

1.4 Patterns, Class Libraries, and Frameworks


Computing power and network bandwidth have increased dramatically over the
past decade. However, the design and implementation of complex software
remains expensive and error prone. Much of the cost and effort stem from the
continuous rediscovery and reinvention of core concepts and components across
the software industry. In particular, the growing heterogeneity of hardware archi-
tectures and diversity of operating system and communication platforms make it
difficult to build correct, portable, efficient, and inexpensive applications from
scratch. Patterns, class libraries, and frameworks are three tools the software
industry is using to reduce the complexity and cost of developing software.
Patterns represent recurring solutions to software development problems
within a particular context. Patterns and frameworks both facilitate reuse by
capturing successful software development strategies. The primary difference is
that frameworks focus on reuse of concrete designs, algorithms, and implementa-
tions in a particular programming language. In contrast, patterns focus on reuse of
abstract designs and software microarchitectures.
Frameworks can be viewed as a concrete implementation of families of design
patterns that are targeted for a particular application domain. Likewise, design
patterns can be viewed as more abstract microarchitectural framework elements
that document and motivate the semantics of frameworks in an effective way.
When patterns are used to structure and document frameworks, nearly every class
in the framework plays a well-defined role and collaborates effectively with other
classes in the framework.
Like frameworks, class libraries are implementations of useful, reusable soft-
ware artifacts. Frameworks extend the benefits of OO (object-oriented) class
libraries in the following ways.
8 Chapter 1: Introduction to ACE

• Frameworks define “semicomplete” applications that embody domain-


specific object structures and functionality. Components in a framework work
together to provide a generic architectural skeleton for a family of related
applications. Complete applications are composed by inheriting from and/or
instantiating framework components. In contrast, class libraries are less
domain specific and provide a smaller scope of reuse. For instance, class
library components, such as classes for strings, complex numbers, arrays, and
bitsets, are relatively low level and ubiquitous across many application
domains.
• Frameworks are active and exhibit “inversion of control” at runtime. Class
libraries are typically passive; that is, they are directed to perform work by
other application objects, in the same thread of control as those application
objects. In contrast, frameworks are active; that is, they direct the flow of
control within an application via event dispatching patterns, such as Reactor
and Observer. The “inversion of control” in the runtime architecture of a
framework is often referred to as the Hollywood Principle: “Don’t call us;
we’ll call you.”
In practice, frameworks and class libraries are complementary technologies.
For instance, frameworks typically use class libraries internally to simplify the
development of the framework. (Certainly, ACE’s frameworks reuse other parts of
the ACE class library.) Likewise, application-specific code invoked by framework
event handlers can use class libraries to perform such basic tasks as string
processing, file management, and numerical analysis.
So, to summarize, ACE is a toolkit packaged as a class library. The toolkit
contains many useful classes. Many of those classes are related and combined into
frameworks, such as the Reactor and Event Handler, that embody semicomplete
applications. In its classes and frameworks, ACE implements many useful design
patterns.

1.5 Porting Your Code to Multiple Operating Systems


Many software systems must be designed to work correctly on a range of
computing platforms. Competitive forces and changing technology combine to
make it a nearly universal requirement that today’s software systems be able to run
on a range of platforms, sometimes changing targets during development.
Networked systems have a stronger need to be portable, owing to the inherent mix
of computing environments needed to build and configure competitive systems in
1.5 Porting Your Code to Multiple Operating Systems 9

today’s marketplace. Standards provide some framework for portability; however,


marketing messages notwithstanding, standards do not guarantee portability
across systems. As Andrew Tanenbaum said, “The nice thing about standards is
that there are so many to choose from” [3]. And rest assured, vendors often choose
to implement different standards at different times. Standards also change and
evolve, so it’s very unlikely that you’ll work on more than one platform that
implements all the same standards in the same way.
In addition to operating system APIs and their associated standards, compiling
and linking your programs and libraries is another area that differs among oper-
ating systems and compilers. The ACE developers over the years have developed
an effective system of building ACE based on the GNU Make tool. Even on
systems for which a make utility is supplied by the vendor, not all makes are
created equal. GNU Make provides a common, powerful tool around which ACE
has its build facility. This allows ACE to be built on systems that don’t supply
native make utilities but to which GNU Make has been ported. Don’t worry if
you’re a Windows programmer using Microsoft or Borland compilers and don’t
have GNU Make. The native Microsoft and Borland build utilities are supported
as well.
Data type differences are a common area of porting difficulty that experienced
multiplatform developers have found numerous ways to engineer around. ACE
provides a set of data types it uses internally, and you are encouraged to use them
as well. These are described later, in the discussion of compilers.
ACE’s OS adaptation layer provides the lowest level of functionality and
forms the basis of ACE’s wide range of portability. This layer uses the Wrapper
Facade [4] and Façade [3] patterns to shield you from platform differences. The
Wrapper pattern forms a relatively simple wrapper around a function, and ACE
uses this pattern to unify the programming interfaces for common system func-
tions where small differences in APIs and semantics are smoothed over. The
Façade pattern presents a single interface to what may, on some platforms, be a
complicated set of systems calls. For example, the ACE_OS::thr_create()
method creates a new thread with a caller-specified set of attributes: scheduling
policy, priority, state, and so on. The native system calls to do all that’s required
during thread creation vary widely among platforms in form, semantics, and the
combination and order of calls needed. The Façade pattern allows the presentation
of one consistent interface across all platforms to which ACE has been ported.
For relatively complex and obviously nonportable actions, such as creating a
thread, you would of course think to use the ACE_OS methods—well, at least
until you read about the higher-level ACE classes and frameworks later in the
10 Chapter 1: Introduction to ACE

book. But what about other functions that are often taken for granted, such as
printf() and fseek()? Even when you need to perform a basic function, it is
safest to use the ACE_OS methods rather than native APIs. This usage guarantees
that you won’t be surprised by a small change in arguments to the native calls
when you compile your code on a different platform.
The ACE OS adaptation layer is implemented in the ACE_OS class. The
methods in this class are all static. You may wonder why a separate namespace
wasn’t used instead of a class, as that’s basically what the class achieves. As we’ll
soon see, one of ACE’s strengths is that it works with a wide variety of old and
new C++ compilers, some of which do not support namespaces at all. We are not
going to list all the supplied functions here. You won’t often use these functions
directly. They are still at a very low level, not all that much different from writing
in C. Rather, you’ll more often use high-level classes that themselves call
ACE_OS methods to perform the requested actions. Therefore, we’re going to
leave a detailed list of these methods to the ACE_OS reference pages.
As you might imagine, ACE contains quite a lot of conditionally compiled
code, especially in the OS adaptation layer. ACE does not make heavy use of
vendor-supplied compiler macros for this, for a couple of reasons. First, a number
of the settings deal with features that are missing or broken in the native platform
or compiler. The missing or broken features may change over time; for instance,
the OS is fixed or the compiler is updated. Rather than try to find a vendor-
supplied macro for each possible item and use those macros in many places in
ACE, any setting and vendor-supplied macro checking is done in one place and
the result remembered for simple use within ACE. The second reason that vendor-
supplied macros are not used extensively is that they may either not exist or may
conflict with another vendor’s macros. Rather than use a complicated combination
of ACE-defined and vendor-supplied macros, a set of ACE-defined macros is used
extensively and is sometimes augmented by vendor-supplied macros, although
this is relatively rare.
The setting of all the ACE-defined compile-time macros is done in one file,
ace/config.h, which we’ll look at in Chapter 2. Many varieties of this config-
uration file are supplied with ACE, matching all the platforms ACE has been
ported to. If you obtain a prebuilt version of ACE for installation in your environ-
ment, you most likely will never need to read or change this file. But sometime
when you’re up for some adventure, read through it anyway for a sampling of the
range of features and issues ACE handles for you.
1.6 Smoothing the Differences among C++ Compilers 11

1.6 Smoothing the Differences among C++ Compilers


You’re probably wondering why it’s so important to smooth over the differences
among compilers, as the C++ standard has finally settled down. There are a
number of reasons.
• Compiler vendors are at various levels of conformance to the standard.
• ACE works with a range of C++ compilers, many of which are still at rela-
tively early drafts of the C++ standard.
• Some compilers are simply broken, and ACE works around the problems.
Many items of compiler capability and disability adjustment are used to build
ACE properly, but from a usage point of view, ACE helps you work with or
around four primary areas of compiler differences:
1. Templates, both use and instantiation
2. Data types, both hardware and compiler
3. Runtime initialization and shutdown
4. Allocating heap memory

1.6.1 Templates
C++ templates are a powerful form of generic programming, and ACE makes
heavy use of them, allowing you to combine and customize functionality in
powerful ways. This brief discussion introduces you to class templates. If
templates are a new feature to you, we suggest that you also read an in-depth
discussion of their use in a good C++ book, such as Bjarne Stroustrup’s The C++
Programming Language, 3rd Edition [11] or C++ Templates: The Complete
Guide by David Vandevoorde and Nicolai M. Josuttis [14]. As you’re reading,
keep in mind that the dialect of C++ described in your book and that implemented
by your compiler may be different. Check your compiler documentation for
details, and stick to the guidelines documented in this book to be sure that your
code continues to build and run properly when you change compilers.
C++’s template facility allows you to generically define a class or function,
and have the compiler apply your template to a given set of data types at compile
time. This increases code reuse in your project and enables you to reuse code
across projects. For example, let’s say that you need to design a class that remem-
bers the largest value of a set of values you specify over time. Your system may
have multiple uses for such a class—for example, to track integers, floating-point
12 Chapter 1: Introduction to ACE

numbers, text strings, and even other classes that are part of your system. Rather
than write a separate class for each possible type you want to track, you could
write a class template:
template <class T> class max_tracker {
public:
void track_this (const T val);
private:
T max_val_;
};

template <class T>


void max_tracker::track_this (const T val)
{
if (val > this->max_val_)
this->max_val_ = val;
return;
}
Then when you want to track the maximum temperature of your home in integer
degrees, you declare and use one of these objects:
max_tracker<int> temperature_tracker;

// Get a new temperature reading and track it


int temp_now = Thermometer.get_temp ();
temperature_tracker.track_this (temp_now);
The use of the template class would cause the compiler to generate code for
the max_tracker class, substituting the int type for T in the class template.
You could also declare a max_tracker<float> object, and the compiler
would instantiate another set of code to use floating-point values. This magic of
instantiating class template code brings us to the first area ACE helps you with—
getting the needed classes instantiated correctly.

Template Instantiation
Many modern C++ compilers automatically “remember” which template
instantiations your code needs and generate them as a part of the final link phase.
In these cases, you’re all set and don’t need to do anything else. For one or more
of the following reasons, however, you may need to take further steps regarding
instantiation.
• You need to port your system to another platform on which the compiler isn’t
so accommodating.
1.6 Smoothing the Differences among C++ Compilers 13

• Your compiler is really slow when doing its magical template autoinstantia-
tion, and you’d like to control it yourself, speeding up the build process.
Compilers provide a variety of directives and methods to specify template
instantiation. Although the intricacies of preprocessors and compilers make it
extremely difficult to provide one simple statement for specifying instantiation,
ACE provides a boilerplate set of source lines you should use to control explicit
template instantiation. The best way to explain it is to show its use. In the
preceding example code, the following code would be added at the end of the
source file:
#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION)
template class max_tracker<int>;
#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA)
#pragma instantiate max_tracker<int>
#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */
This code will successfully build on all compilers that correctly handle automatic
instantiation, as well as all compilers ACE has been ported to that customarily use
explicit template instantiation for one reason or another. If you have more than
one class to instantiate, you add more template class and #pragma
instantiate lines to cover them.
Be careful when deciding to explicitly instantiate templates in projects that use
the standard C++ library. The templates in the standard library often use other, not
so obvious, templates, and it’s easy to end up in a maze of instantiation statements
that change between compilers. It’s much safer to let the compiler automatically
instantiate template classes whenever possible.

Use of Types Defined in Classes That Are Template Arguments


A number of ACE classes define types as traits of that class. For example, the
ACE_SOCK_Stream class defines ACE_INET_Addr as the PEER_ADDR type.
The other stream-abstracting classes also define a PEER_ADDR type internally to
define the type of addressing information needed for that class. This use of traits
will be seen in more detail in Section 7.6 when using the ACE_Svc_Handler
class and in Chapter 17 when discussing ACE_Malloc. For now, though, view
the use of traits as an example of this problem: If a template class can be used with
one of these trait-defining classes as a template argument, the template class may
need to know and use the trait type.
You’d think that the template argument class could be accessed as if the class
were used by itself. But not so; some older compilers disallow that. ACE works
around the limitation and keeps your code compiler neutral by defining a set of
14 Chapter 1: Introduction to ACE

macros for the cases in ACE when the information is required together. In the case
of the ACE_SOCK_Stream class’s usage, when the addressing trait is also
needed, ACE defines ACE_SOCK_STREAM, which expands to include the
addressing type for compilers that don’t support typedefs in classes used as
template arguments. It expands to ACE_SOCK_Stream for compilers that do
support it. The many uses of this tactic in ACE will be noted for you at the points
in the book where their use comes up.

1.6.2 Data Types


Programs you must port to multiple platforms need a way to avoid implicit reli-
ance on the hardware size of compiler types and the relationships between them.
For example, on some hardware/compiler combinations, an int is 16 bits; in
others, it is 32 bits.2 On some platforms, a long int is the same as an int,
which is the same length as a pointer; on others, they’re all different sizes. ACE
provides a set of type definitions for use when the size of a data value really
matters and must be the same on all platforms your code runs on. They are listed
in Table 1.1, with some other definitions that are useful in multiple-platform
development. If you use these types, your code will use properly sized types on all
ACE-supported platforms.

1.6.3 Runtime Initialization and Rundown


One particular area of platform difference and incompatibility is runtime initial-
ization of objects and the associated destruction of those objects at program
rundown. This difference is particularly true when multiple threads are involved,
as there is no compiler-added access serialization to the time-honored method of
automatic initialization and destruction of runtime data: static objects. So
remember this ACE saying: Statics are evil! Fortunately, ACE provides a portable
solution to this problem in the form of three related classes:
• ACE_Object_Manager. As its name implies, this class manages objects.
The ACE library contains a single instance of this class, which when initial-
ized instantiates a set of ACE objects that are needed to properly support the
ACE internals and also destroys them at rundown time. ACE programs can

2. It wouldn’t surprise us if there were also other possible values, such as 8 bits or 64 bits. The point
is: Don’t count on a particular size.
1.6 Smoothing the Differences among C++ Compilers 15

Table 1.1. Data Types Defined by ACE

Type Meaning
ACE_INT16, ACE_UINT16 16-bit integer, signed and unsigned
ACE_INT32, ACE_UINT32 32-bit integer, signed and unsigned
ACE_UINT64 64-bit unsigned integer; on platforms without native
64-bit integer support, ACE provides a class to
emulate it
ACE_SIZEOF_CHAR Number of bytes in a character
ACE_SIZEOF_WCHAR Number of bytes in a wide character
ACE_SIZEOF_SHORT Number of bytes in a short int
ACE_SIZEOF_INT Number of bytes in an int
ACE_SIZEOF_LONG Number of bytes in a long int
ACE_SIZEOF_LONG_LONG Number of bytes in a long long int; on plat-
forms without native long long support, this is 8,
and ACE_UINT64 is ACE_U_LongLong
ACE_SIZEOF_VOID_P Number of bytes in a pointer
ACE_SIZEOF_FLOAT Number of bytes in a float
ACE_SIZEOF_DOUBLE Number of bytes in a double
ACE_SIZEOF_LONG_DOUBLE Number of bytes in a long double
ACE_BYTE_ORDER Has a value of either ACE_BIG_ENDIAN or
ACE_LITTLE_ENDIAN

make use of the Object Manager by registering objects that must be destroyed.
The Object Manager destroys all the objects registered with it at rundown
time, in reverse order of their registration.
• ACE_Cleanup. ACE_Object_Manager uses this class’s interface to
manage object life cycles. Each object to be registered with the Object
Manager must be derived from ACE_Cleanup.
• ACE_Singleton. The Singleton pattern [3] is used to provide a single
instance of an object to a program and provide a global way to access it. This
object instance is similar to a global object in that it’s not hidden from any part
of the program. However, the instantiation and deletion of the object is under
control of your program, not the platform’s runtime environment. ACE’s
16 Chapter 1: Introduction to ACE

singleton class also adds thread safety to the basic Singleton pattern by using
the Double-Checked Locking Optimization pattern [5]. The double-checked
lock ensures that only one thread initializes the object in a multithreaded
system.
The two most common ways to be sure that your objects are properly cleaned
up at program rundown are described next. Which one you use depends on the
situation. If you want to create a number of objects of the same class and be sure
that each is cleaned up, use the ACE_Cleanup method. If you want one instance
of your object accessible using the Singleton pattern, use the ACE_Singleton
method.
• ACE_Cleanup method. To be able to create a number of objects of a class
and have them be cleaned up by the ACE Object Manager, derive your class
from ACE_Cleanup, which has a cleanup() method that the Object
Manager calls to do the cleanup. To tell the Object Manager about your
object—so it knows to clean it up—you make one simple call, probably from
your object’s constructor:
ACE_Object_Manager::at_exit (this);

• ACE_Singleton method. Use the ACE_Singleton class to create one


and only one instance of your object. This class uses the Adapter pattern [3] to
turn any ordinary class into a singleton optimized with the Double-Checked
Locking Optimization pattern. ACE_Singleton is a template class with this
definition:
template <class TYPE, class ACE_LOCK>
class ACE_Singleton : public ACE_Cleanup

TYPE is name of the class you are turning into a singleton. ACE_LOCK is the type
of lock the Double-Checked Locking Optimization pattern implementation uses to
serialize checking when the object needs to be created. For code that operates in a
multithreaded environment, use ACE_Recursive_Thread_Mutex. If you are
writing code without threads, you should use ACE_Null_Mutex, which
provides the proper interface but does not lock anything. This would be useful if
your main factor in choosing the Singleton pattern is to provide its “instantiate
when needed” semantics, as well as have the Object Manager clean up the object.
As an example, assume that you have a class named SystemController and
that you want a single instance of it. You would define your class and then
typedef ACE_Singleton<SystemController,
ACE_Recursive_Thread_Mutex> TheSystemController;
1.6 Smoothing the Differences among C++ Compilers 17

When you need access to the instance of that object, you get a pointer to it from
anywhere in your system by calling its instance() method. For example:
SystemController *s = TheSystemController::instance();
As we’ve seen, the ACE Object Manager is quite a useful and powerful object.
You need to remember only two rules in order to successfully make use of this
facility.
1. Never call exit() directly.
2. Make sure that the Object Manager is initialized successfully.
The first is easy. Remember all the registrations with the Object Manager to
request proper cleanup at rundown time? If you call exit(), your program will
terminate directly, without the Object Manager’s having a chance to clean
anything up. Instead, have your main() function simply do a return to end. If
your program encounters a fatal condition inside a function call tree, either return,
passing error indications, or throw an exception that your main() function will
catch so it can cleanly return after cleaning up. In a pinch, you may call
ACE_OS::exit() instead of the “naked” exit(). That will ensure that the
Object Manager gets a chance to clean up.
Object Manager initialization is an important concept to understand. Once you
understand it, you can often forget about it for a number of platforms. The Object
Manager is, effectively, a Singleton. Because it is created before any code has a
chance to create threads, the Object Manager doesn’t need the same protection
that Singletons generally require. And, what object would the Object Manager
register with for cleanup? The cleanup chain has to end somewhere, and this is
where. As we said, statics are generally evil.
However, on some platforms, statics are not completely evil, and the Object
Manager is in fact a static object, initialized and destroyed properly by the plat-
form’s runtime environment, even when used in combination with shared
libraries, some of which are possibly loaded and unloaded dynamically. On these
platforms,3 you can usually ignore the rule for properly initializing the Object
Manager.4 On the others, however, the Object Manager needs to be initialized and
terminated explicitly. For use cases in which you are writing a regular C++ appli-
cation that has the standard int main (int argc, char *argv[])
entry point or the wide-character-enabled ACE_TMAIN entry point shown in

3. The config.h file for these does not define ACE_HAS_NONSTATIC_OBJECT_MANAGER.


4. No, Windows is definitely not one of those platforms.
18 Chapter 1: Introduction to ACE

Section 1.7, ACE magically redefines your main() function and inserts its own,
which instantiates the Object Manager on the runtime stack and then calls your
main() function. When your main() function returns, the Object Manager is
run down as well. (This is an example of why your code should not call exit():
You’d bypass the Object Manager cleanup.)
If your application does not have a standard main() function but needs to
initialize and run down the Object Manager, you need to call two functions:
1. ACE::init() to initialize the Object Manager before any other ACE opera-
tions are performed.
2. ACE::fini() to run down the Object Manager after all your ACE opera-
tions are complete. This call will trigger the cleanup of all objects registered
with the Object Manager.
This may be necessary for Windows programs that have a WinMain() function
rather than the standard main() function and for libraries that make use of ACE
but the users of the library do not. For libraries, it is advantageous to add initialize
and finalize functions to the library’s API and have those functions call
ACE::init() and ACE::fini(), respectively. In case you’re writing a
Windows DLL (dynamic link library) and thinking you can make the calls from
DllMain(), don’t go there. It’s been tried.
You can also build ACE on Windows with
#define ACE_HAS_NONSTATIC_OBJECT_MANAGER 0
in your config.h file before including ace/config-win32.h. (Chapter 2
describes ACE’s configuration.) This removes the need to explicitly call
ACE::init() and ACE::fini() but may cause problems when using
dynamic services.

1.6.4 Allocating Heap Memory


Dynamic memory allocation from the runtime heap is a common need in most
programs. If you’ve used memory allocation functions from C, you’ve certainly
written code like this:
char *c = (char *)malloc (64);
if (c == 0)
exit(1); /* Out of memory! */
When transitioning to C++, this sort of code was replaced by:
1.7 Using Both Narrow and Wide Characters 19

char *c = new char[64];


if (c == 0)
exit(1); /* Out of memory! */
Straightforward stuff—until the C++ standard settled down. Now operator
new() throws an exception if the memory allocation request fails. However, you
probably need to develop code to run in some C++ runtime environments that
return a 0 and some that throw an exception on failure. ACE also supports a mix of
these environments, so it uses a set of macros that adapt to the compiler’s model to
what ACE expects. Because it was built in the days when a failed allocation
returned a 0 pointer, ACE uses that model internally and adapts the new exception
throwing model to it. With the macros, the preceding code example becomes:
char *c;
ACE_NEW_NORETURN (c, char[64]);
if (c == 0)
exit(1); /* Out of memory! */
The complete set of ACE memory allocation macros is listed in Table 1.2.

1.7 Using Both Narrow and Wide Characters


Developers outside the United States are acutely aware that many character sets in
use today require more than one byte, or octet, to represent each character. Char-
acters that require more than one octet are referred to as “wide characters.” The
most popular wide-character standard is ISO/IEC 10646, the Universal Multiple-
Octet Coded Character Set (UCS). Unicode is a separate standard but can be
thought of as a restricted UCS subset that uses two octets for each character
(UCS-2). Many Windows programmers are familiar with Unicode.
C++ represents wide characters with the wchar_t type, which enables
methods to offer multiple signatures that are differentiated by their character type.
Wide characters have a separate set of C string manipulation functions, however,
and existing C++ code, such as string literals, requires change for wide-character
usage. As a result, programming applications to use wide-character strings can
become expensive, especially when applications written initially for U.S. markets
must be internationalized for other countries. To improve portability and ease of
use, ACE uses C++ method overloading and the macros described in Table 1.3 to
use different character types without changing APIs.
For applications to use wide characters, ACE must be built with the
ACE_HAS_WCHAR configuration setting, which most modern platforms are
20 Chapter 1: Introduction to ACE

Table 1.2. ACE Memory Allocation Macros

Macro Action
ACE_NEW(p, c) Allocate memory by using constructor c and
assign pointer to p. On failure, p is 0 and
return;
ACE_NEW_RETURN(p, c, r) Allocate memory by using constructor c and
assign pointer to p. On failure, p is 0 and
return r;
ACE_NEW_NORETURN(p, c) Allocate memory by using constructor c and
assign pointer to p. On failure, p is 0 and con-
trol continues at next statement.

Table 1.3. Macros Related to Character Width

Macro Purpose
ACE_HAS_WCHAR Configuration setting that enables ACE’s
wide-character methods
ACE_USES_WCHAR Configuration setting that directs ACE to
use wide characters internally
ACE_TCHAR Matches ACE’s internal character width;
defined as either char or wchar_t,
depending on the lack or presence of
ACE_USES_WCHAR
ACE_TMAIN Properly defines program’s main entry
point for command line argument type,
based on ACE_USES_WCHAR
ACE_TEXT(str) Defines the string literal str correctly,
based on ACE_USES_WCHAR
ACE_TEXT_CHAR_TO_TCHAR(str) Converts a char * string to
ACE_TCHAR format, if needed
ACE_TEXT_WCHAR_TO_TCHAR(str) Converts a wchar_t * string to
ACE_TCHAR format, if needed
ACE_TEXT_ALWAYS_CHAR(str) Converts an ACE_TCHAR string to
char * format, if needed
1.8 Where to Find More Information and Support 21

capable of. Moreover, ACE must be built with the ACE_USES_WCHAR setting if
ACE should also use wide characters internally. The ACE_TCHAR and
ACE_TEXT macros are illustrated in examples throughout this book.
ACE also supplies two string classes—ACE_CString and
ACE_WString—that hold narrow and wide characters, respectively. These
classes are analogous to the standard C++ string class but can be configured to
use custom memory allocators and are more portable. ACE_TString is a
typedef for one of the two string types depending on the ACE_USES_WCHAR
configuration setting.

1.8 Where to Find More Information and Support


As you’re aware by the number and scope of items ACE helps with—from
compiling to runtime—and from a perusal of the Contents—not to mention the
size of this book!—you may be starting to wonder where you can find more infor-
mation about ACE, how to use all its features, and where to get more help. A
number of resources are available: ACE reference documentation, ACE kits, user
forums, and technical support.
The ACE reference documentation is generated from specially tagged
comments in the source code itself, using a tool called Doxygen.5 That reference
documentation is available in the following places:
• On the CD-ROM included with this book
• At Riverace’s web site: http://www.riverace.com/docs/
• At the DOC group’s web site, which includes the reference documentation for
ACE and TAO (The ACE ORB) for the most recent stable version, the most
recent beta version, and the nightly development snapshot: http://
www.dre.vanderbilt.edu/Doxygen/
ACE is, of course, freely available in a number of forms from the following
locations.
• The complete ACE 5.3b source and prebuilt kits for selected platforms are on
the included CD-ROM.

5. For more information on Doxygen, please see http://www.doxygen.org/.


22 Chapter 1: Introduction to ACE

• Kits for the currently supported ACE versions are available at Riverace’s web
site: http://www.riverace.com.
• Complete sources for the current release, current BFO (bug fix only) beta, and
the most recent beta versions of ACE are available from the DOC group’s web
site: http://download.dre.vanderbilt.edu/. The various types
of kits are explained in Section 2.1.
A number of ACE developer forums are available via e-mail and Usenet news.
The authors and the ACE developers monitor traffic to these forums. These
people, along with the ACE user community at large, are very helpful with ques-
tions and problems. If you post a question or a problem to any of the following
forums, please include the information in the PROBLEM-REPORT-FORM file
located in the top-level directory of the ACE source kit:
• comp.soft-sys.ace newsgroup.
[email protected] mailing list. To join this list, send a request
to [email protected]. Include the following
command in the body of the e-mail:
subscribe ace-users [emailaddress@domain]

You must supply emailaddress@domain only if your message’s From


address is not the address you wish to subscribe. If you use this alternative
address method, the list server will require an extra authorization step before
allowing you to join the list.
Messages posted to the ace-users list are forwarded to the comp.soft-
sys.ace newsgroup, but not vice versa. You can search an archive of the
comp.soft-sys.ace newsgroup at http://groups.google.com.
Although the level of friendly assistance on the ACE user forums is extraordi-
nary, it is all on a best-effort, volunteer basis. If you’re developing commercial
projects with ACE, you may benefit greatly from the technical support services
that are available. Using technical support allows you and your development team
to stay focused on your project instead of needing to learn all about ACE’s inter-
nals and to get involved in toolkit maintenance.
Riverace Corporation is the premier support provider for the ACE toolkit. You
can learn all about Riverace’s services at http://www.riverace.com. A
number of other companies have recently begun providing support services for
ACE and TAO worldwide. A current list is available at http://
www.cs.wustl.edu/~schmidt/commercial-support.html.
1.9 Summary 23

1.9 Summary
This chapter introduced the ACE toolkit’s organization and described some foun-
dational concepts and techniques that you’ll need to work with ACE. The chapter
covered some helpful macros and facilities provided to smooth out the differences
among C++ compilers and runtime environments, showed how to take advantage
of both narrow and wide characters, and, finally, listed some sources of further
information about ACE and the available services to help you make the most of
ACE.
This page intentionally left blank
Chapter 2
How to Build and Use ACE in Your
Programs

Traditional, closed-source libraries and toolkits are often packaged as shared


libraries (DLLs), often without source code. Although ACE is available in install-
able packages for some popular platforms, its open-source nature means that you
can not only see the source but also change it to suit your needs and rebuild it.
Thus, it is very useful to know how to build it from sources.
You will also, of course, need to build your own applications. This chapter
shows how to include ACE in your application’s source code and build it.

2.1 A Note about ACE Versions


ACE kits are released periodically as either of two types:
1. Release—two numbers, such as 5.3. These versions are stable and well tested.
You should use release versions for product development unless you need to
add a new feature to ACE in support of your project.
2. Beta—three numbers, such as 5.3.4. These versions are development snap-
shots: the “bleeding edge.” They may contain bug fixes above the previous
release, but they may also contain more bugs or new features whose effects
and interactions have not yet been well tested.
The first beta kit following each release—for example, 5.3.1—is traditionally
reserved for bug fixes to the release and usually doesn’t contain any new features
25
Exploring the Variety of Random
Documents with Different Content
(Kokoelmasta "Tunnustuksia", ilm. 1922).

Varsin hauskaa huumoria on runossa "Rippikoulupojat".


Juhlallisesti katsovat he ensimmäistä kelloaan, joka käy liian hitaasti,
sillä koskaan ei ehdi suureksi. "Totisesti, totisesti sanon minä teille"
häipyy vähitellen arkiseen pakinaan. Urut kaikuvat vielä heidän
korvissaan heidän katsoessaan "Chaplinia palosotilaana".

Kristus, som korsfästs för dem, ha de förgätit,


Innan deras byxor mist sina veck.
Fastän de av honom ha druckit och ätit
gå de och fundera på rackarstreck.

Kuinka iskevästi johtuukaan mieleen Hjalmar Söderbergin ironia!


Mikä omituinen käänne! Naturalismin jumalat, joita särkemään
Heidenstam ja Levertin nousivat, on taas nostettu jalustalle.

Kauniisti ilmaistu on hellyys elämän pieniä asioita kohtaan


kuoleman elämyksen yhteydessä nuoren lyyrikon Ebbe Linden (s.
1897) runossa "Nuoruus", tuoden mieleen eräitä Liliencronin pieniä
unohtumattomia runoja. Linde on samalla ainoa mitattoman,
meilläkin niin muotiin tulleen runouden edustaja
muodonkunnioittajien joukossa.

Ilmeisesti hieno ja kultivoitu lyyrikkohahmo on Sten Selander (s.


1891), kuulemma päätään pitempi muuta nuorta polvea — tosin vain
konkreettisessa mielessä. Keskitetyn lyyrillisen ilmaisun on hän
löytänyt runossa "Kuiva puu" ("Tie kotiin", ilm. 1920). Puu rukoilee
sadetta ja uutta kukintaa, ja vastaus tulee salaman muodossa, joka
tekee puusta jättiläismäisen, tulta leimuavan kukan. Runo muistuttaa
Nietzschen runoa "Pinja ja salama". Valitettavasti on Selanderkin
viimeisessä kirjassaan kääntynyt runopukuiseen koseriaan. Lämmin
myötätunto kaikkea pientä inhimillistä kohtaan puhuu tästäkin
kirjasta. Kiitäessään junassa hän ajattelee ohikiitävien maisemien
tuhansissa kodeissa asuvia ihmisiä, joiden kanssa ystävystymiseen
hänen pieni elämänsä ei riitä.

Kuten edelläolevasta on käynyt ilmi, kumpuaa Ruotsin nuori


lyriikka perifeerisistä kulttuurielämyksistä, ei sentraalisista,
alkuperäisistä tunteista. Runsas kulttuuri ei suinkaan ole vika,
ajateltakoon Heidenstamia ja Levertiniä. Nuorten lyyrikoiden
löytöretket kulttuurin maailmoihin näyttävät kuitenkin säännöllisesti
pysähtyneen rajoille. Yksinäinen ilmiö Bertil Malmberg (s. 1889), joka
on ruotsintanut Schillerin esteettisfilosofisen runouden, edustaa
kokoelmassaan "Orfika" (ilm. 1923) jonkinlaista gnostillista
romantiikkaa, joka etäisesti muistuttaa Stagneliusta. Helleeninen
henkäys hänen runossaan "Neitsyt" on varsin hentoinen. Rydbergiä
muistuttava kaunis, idealistinen uskonto on Erik Blombergilla (s.
1894), joka kokoelmaansa "Maa" (1920) on kirjoittanut hymnin
hengelle ja runossa "Nike" laulaa ihmisajatuksen kunniaa.

Luonnontunne on Ruotsin nuoressa lyriikassa hämmästyttävän


heikosti kehittynyt. Ragnar Jändel(s. 1895), ilmeisestikin hersyvä ja
heleätunteinen lyyrikko, joka v:sta 1917 on julkaissut viisi
kokoelmaa, on runossa "Sataa" tavannut rytmillisestikin eheän ja
harmoonisen tunnelman. Toisella tavalla lähellä maata ja kansaa
ovat Dan Andersson (1888-1920), jonka "Mustissa balladeissa" on
eräänlaista boheemiviisautta. Hänen muutamissa runoissaan on
tunnetta ja persoonallista äänenpainoa. Vahvasti samanlainen
aihepiiri on Gustaf Johanssonin (s. 1891) kirjassa "Metsämiehen
lauluja ja maantieballadeja" (1913), jotka nekin usein tihenevät
verrattain proosalliseen sananlaskuviisauteen.
Erääseen merkilliseen seikkaan saattaa vielä kiinnittää huomionsa.
Nuoren Ruotsin runouteen sisältyy myöskin poliittista lyriikkaa, ja se
on voimakkaasti ententeystävällistä. Se näkyy muun muassa Karl
Asplundin gallialaisen ylväästä runosta "Quand même" (Kokoelmasta
"Sankarit", kaksitoista balladia 1923, nähnyt toisen painoksen).
Kirsikkapuu, jonka pakenevat saksalaiset ovat kaataneet, puhkeaa
kuollessaan uljaimpaan kukkaansa. Sen ylpeät kukinnot ovat kuin
säteilevä gallialainen lause "Quand même" ("Kaikesta huolimatta").
Antipatia Saksan militarismia kohtaan, puhuu myöskin kommunismiin
taipuvaisen Ture Nermanin (s. 1886) runosta "Äiti". Runonsa
"Kaunein laulu" hän omistaa tuntemattomalle pariisilaisylioppilaalle,
josta olisi voinut tulla uusi Musset.

Siten olemme läpikäyneet pääasiallisimmat lyyrilliset aihepiirit,


jotka luonnehtivat Nuoren Ruotsin lyriikkaa. Kieltää ei voi, että
satomme on ollut vähäinen. Meidän on täytynyt todeta, että kaikki,
mikä luo elinvoimaista lyriikkaa, syvät, yksilölliset elämykset ja niiden
kypsyttämä persoonallinen originaliteetti, elävän minuuden
liikunnosta lähteneet rytmit, värikylläinen ja plastillinen mielikuvitus
ovat hyveitä, joita nuoren Ruotsin lyriikka ei tunne. Sen tunnussana
ja uskonto tuntuu olevan: "Lähemmä jokapäiväisyyttä!" Mutta tämä
periaate ei ole koskaan luonut suurta lyyrillistä perioodia. Enemmän
alkuperäisyyttä, syvyyttä ja tuoreutta on sittenkin Saksan nuoressa
lyriikassa, jonka alkuosasiinsa hajonneessa sielussa huohottaa
ilmaisuaan odottavan uuden panteistisen maailmantunteen ääni.
Runouden olemassaolo on yhtä välttämätöntä kuin se, että ihmiset
syntyvät ja kuolevat ja että sade ja auringonpaiste vuorottelevat
maan päällä. Mutta sitä vapauttavaa sanaa, jota me kukin
kohdastamme etsimme, ei anneta meille ulkoapäin. Se on meidän
itsemme löydettävä.
Lauri Viljanen.
RUOTSIN NUORTA LYYRILLISTÄ
TAIDETTA.

Kolme runoa, suomentanut Lauri Viljanen.

AAMUN SYDÄN.

Anders Österling.

Lähelle ikuista aamua tulla määränä vaelluksen oli mulla.


Kaiken, minkä elämä soi kestin ma, siintävä aamunkoi aina
mun eelläni loisti. Lähemmä aamun sydäntä sain, kasteesta
nummien kukkivain kimposi kiuru ja yön jo poisti.

ONNEN HETKI.

Erik Lindorm.
Käsivarteni lastako tuudittaa, ja sen silmissä kuvani on? Ja
ulapat välkkyy, ja lämmin on maa ja taivas hattaraton!

Mitä aikoja on, mitä vuosia nää,


ken oon, mikä nimeni mun?
Sa naurava käärö, sa vaalea pää,
miten sain ma syliini sun?

Ma elän, ma elän! Ah, ennemmin ma miss' olen ollutkaan?


Kai varroin ma vuosia miljoonin tätä hetkeä ainostaan.

SATAA.

Ragnar Jändel.

Herää ja tule portahille, armas!


Kauniin harmaita pilviä kertynyt on.
Tuoksuvaiseen tummaan yöhön hiljaa
sade lankee.

Kätes ojenna, ah, miten suloisesti


pilvistä valuu viileitä pisaroita!
Syvään tunne, mun armahain, maan kiitos
taivahalle!

Kuivat lehdet kahisee kevyesti,


nauttien ojentuvat poltetut yrtit.
Kiittäin huokuu vainiot, jotka hämyn
halki loistaa.
Ehtynyt puro alkaa solista hiljaa,
ja sen vaiheilla, pähkinäpensastossa,
harmaiden pilvien alla laulaa harmaa
satakieli.
NELJÄ RUNOA.

Uuno Kailas.

RUNO RISTIINNAULITUILLE.

Ristinpuiden varjo lankeaa mittaamattomana maailman yli.


Nähkää se pilvien hartioilla ja kaikkien vuosituhansien
kasvoilla.

Näettekö: ristiinnaulittuna elämän sydän ja elämän


nuoruus, jokainen uusi ääni, joka huomenna on kaikkien
uskonto, jokaisen uuden päivän aurinko, jokainen uusi
vapahtaja — vain Messiaita ristiinnaulitaan, ei epäjumalia!

He rakensivat ristinpuita maan kuninkaille.


Mutta heidän lapsensa suutelevat ristejä.
Pian kuolevat heidän askeleensa pimeään.
Mutta valo ei ole pakeneva ristinpuiden
ympäriltä,
sillä jokainen ristiinnaulittu sydän
oli tähti!

RUNO RUNOSTA.

Totuuden lähteellä sä syvin lapsensilmin uneksut ja leikit


tähdillä ja auringolla.

Maan kasvot jälleen nuoriks suutelet.


Ja tuuli vie
sun hengitykses tuoksun meren yli.

Sun kätes ovat rikkaat hyvyydestä. Sä niillä sydämiä


punnitset ja loputtoman valon siroitat yön peltoon.

Ja kaikki tähdet rakastavat silmiäsi. Ja tomust' alkaa


avaruus sun jalkojesi luota, miss' onnellinen kerjäläinen
polvistuu.

TYHMÄT JA VIISAAT.

(Sikermästä lapsifantasioja.)

Minä nauran auringolle.


Sekin nauraa minulle.
Se nauraa niinkuin äiti.
On tyhmää nauraa auringolle.
Isä ja äiti eivät koskaan naura sille.

Sillä he ovat isoja ihmisiä.


Ja isot ihmiset ovat viisaita.
Ja viisaat eivät näe mitään.
Viisaat eivät ymmärrä mitään.
Viisaat eivät tunne aurinkoa.

Mutta minä olen tyhmä ja nauran auringolle. Minä melkein


luulen, aurinko, että sinäkin olet tyhmä.

Me nauramme viisaita, aurinko.

SUOMALAINEN SONETTIPARAATI.

Kas, kaarti paraatihin ratsastaa,


sonetti-univormu sorja yllä.
Hei heppa, muista: jalan käyttelyllä
nyt ettet loukkaa arvostelijaa!

Ken lurjus sapelinsa kohottaa!


Se pian tuppeen. Tiedättehän kyllä:
on ero paraatilla, miekanmittelyllä.
Siis vielä kerran tarkoin katsokaa.

ett' univormussanne moitteeton


on joka rytmi-sauma, riimi-nappi,
ja että ryhti teillä uljas on.
Vois muuten paisua sen herran sappi, ken runoparaatista
antaa tuomion — ja laulajall' ois eessä Nälkälappi!
KERTOMUS IO-HUISTA.

E. Ahtela.

Vuonna 190- kierteli Sallan tuntureita ja Nuortin ja Sompion kyliä


viisi sutta, väliin joku useampi, väliin vähempi, ja tämä lauma oli
laajalti kuuluisa. Sen perässä olivat Sallan ja Lapin parhaat pyytäjät
lipuneet, sen jäljessä oli viikkoja ja kuukausia samoiltu, sitä oli
vaanittu, sen tietä oli koetettu katkaista. Tätä laumaa johti
kummallisen näköinen hukka. Se oli pitkänomainen, laiha, hiukan
tavallista paikkulaisempi, sen niskassa olkaluitten päällä oli aina
pystyssä oleva karvatupsu, ja sen laiha, jäntereinen kaula oli
venähtänyt kieroon. Jo kaukaa sen tunsi juuri kaulansa vuoksi. Miten
se oli sen saanut, ei kukaan tietänyt, mutta se teki sen kuuluisaksi.
Kun useilla muilla metsän asujilla tuollainen vika olisi tehnyt
omistajansa halvaksi, jopa naurunalaiseksi, niin sudelle se oli arvon
merkkinä. Sillä jokainen tiesi, ettei tuo vika ollut itsestään tullut, sen
täytyi aiheutua jostakin äärimmäisestä voimainkoetuksesta. — Tämä
susi oli Io-hui.

Io-hui, kuka ei häntä tuntisi. Nuorusella ja livaaralla Kuusamossa


hänestä puhutaan, kaukana Inarin Petshikkotunturilla, jolla on ennen
kasvanut mäntyjä, mutta joka nyt on paljas, häntä mainitaan. Mutta
se paikka, jossa hän oleskelee eniten, on Sallan, Nuortitunturin ja
Kurtin välillä.

Häntä ei kukaan ole saavuttanut eikä hänen laumaansa. Ei voida


käsittää, mikä hänet aina pelastaa, mikä ylhäinen voima hänessä on.
Aivan rohkeasti ihmisasunnoille hän tulee, kun on mitä syvin lumi
maassa. Silloin sanoo poromies: nyt sen on loppu, ja ottaa pyssynsä.
Pekka Aatsinki sanoo: no nyt; ja hän ottaa sivakkansa. Kun Pekka
Aatsinki lähtee suden perään, on se suden hukka. Mutta Io-huita
ajettuaan takaa tulee Pekka Aatsinki takaisin ilman taljaa.

Io-huilla on kummalliset tapansa. Keväisin kun lumi alkaa sulaa,


kun kovien hevoshankien aika on käsissä, se katoaa. Kun
ensimmäiset lumihiutaleet syksyisin alkavat; pudota, ilmestyy se
jälleen.

Siinä oli ikäänkuin jotakin uhmaa, tuossa ilmestymisessä Sallan


maille, aina kun talven nietokset alkavat kasaantua paikoilleen.
Luottaako hän uhmarohkeuteensa, vai perustaako hän menettelynsä
joihinkin laskelmiin! On niinkuin olisi jotakin tarkoitusta tuolla
saapumisella alamaihin aina talven alussa. Olisikohan niin, ettei Io-
hui voi unohtaa mitä täällä on tapahtunut? se on meidän
ajatuksemme. Eihän kukaan muu tiedä Io-huin aikaisemmista
vaiheista.

Mutta Io-hui, ystävä parka, minä tiedän, minkä harjun kumpuloilla


keväisin makaat, kun Lapin moniviikkoinen päivä omituista valoansa
luo. Ja ehkä senvuoksi lemminkin sinua niin, kun meidän
lempiseutumme on sama, kun kummankin kaiho valtavasti samaan
sydänmaahan liitää. Kun sinä olet tämän vuoksi niinkuin luuta minun
luustani ja lihaa minun lihastani. Niin, Io-hui, eikö olekin ihana se
seutu! Eikö ole mahtava se maa.

Nuortti!

Nuortti! Tunnetko nuo äärettömät avaruudet leveän rajalinjan


kahden puolen, jota Suomen ja Venäjän rajaksi sanotaan ja joka
kulkee laajoja kankaita ja rämeitä halki? Tunnetko tuon avaran
erämaan, jossa vielä luonto on omana itsenään, jossa on 160 virstaa
lähimpien kylien välillä. Oletko levännyt talvisena päivänä, kun
pakkanen paukkuu puissa, Kuorvun harjulla, katsellen Ihmisten
raitiota, joka hitaasti, pitkänä kulkee Martista Nuorttijärvelle.
Kaukaisista seuduista on siinä miehiä, jotka ovat tukinajoon Nuorttiin
lähteneet; Ruotsin rajalta, Kolarin saarelta ja Alkkulasta on siellä
miestä, jotka ovat kodeistaan lähteneet paremmille ansioille, siellä
on väkeä Paakkolasta, Kemijoelta ja Yläsimosta asti, ja ne palaavat
takaisin tuhat markkaa taskussa. Martissa ovat ne kokoontuneet ja
pitkänä raitiona, katso, 15 hevosta, lähteneet pitkälle viime
taipaleelle. Mutta jos leipä loppuu, jos liha jää ainoaksi ravinnoksi
viikko- ja kuukausiksi, silloin alkaa kamala keripukki raivota, silloin
lähin toveri istuttaa sairaan poron ahkioon ja silloin suunnataan
takaisin, ensin Marttiin, sitten sisemmäs Suomeen, kauas lääkärin
asuinpaikkaa kohden.

Nuortti! mikä kaiku sinun nimelläsi onkaan minulle, mikä verraton


maa sinä olet. Sinun laajat vuomasi, joita vain suuremmat eläimet
kahlovat, sinun tunturisi, joille yksin sudet ja kiiruna nousevat! Sinun
valtava jokesi, johon lohi nousee kaksi kertaa vuodessa! Mutta
ensiksi ja viimeksi: sinun lukemattomat riekkosi. Niitä kulkee täällä,
niitä juoksee tuolla. Ne eivät pelkää mitään. Mörisevää karhua ne
kuuntelevat pystypäisinä, sivuuttavaa raitiota ne katselevat sylen
kahden päästä, ja kun tukkireet lasketaan vaaroja alas, joutuvat ne
varomattomuudessaan myötään niitten alle.

Tätä seutua sinä lemmit niinkuin minäkin, Io-hui. Tänne sinä


haluaisit asettua rauhaan, eikä mikään sinua enää saisi jättämään
Nuorttia, Io-hui.

Joo, kai!

*****

Kun Io-hui toisena syksynä senjälkeen, kun hän oli jäänyt


yksikseen, makasi Nurmitunturilla ja katseli, kuinka alhaalla
jokivarsilla ja notkoissa ensimmäiset hallat alkoivat utuisina nousta
vetisistä maista, kuinka talvi teki tuloaan, vapautuivat hänen
aatoksensa äkkiä ja lähtivät liitämään. Ne liitivät pitkin harjuja ja
rinteitä, jotka hän tunsi, pitkin ihanaa Kolsanharjua, joka on
vierinkivistä muodostunut ja joka ennen on ollut merenrantana,
pitkin laajojen vuomien reunoja, ne liitivät eteläänpäin, Onkamoon ja
Hautajärveen ja Sieppiin, tuolle viisi peninkulmaa leveälle alueelle,
joka kasvaa vain kuusia, pitkiä, pilviä piirteleviä kuusia, mutta
mäntyjä ei näe missään, pitkin ihmeellistä Ainoan petäjän selkää
noustakseen taasen pohjoisempaan, alaspäin Sallajoen juoksua,
Saukoskelle, Marttiin. Kaikille noille maa-aloille, jotka hän niin hyvin
tunsi, jotka hän oli ristiin rastiin samoillut, joita hän oli talvin
kahlonut.

Ja kun hänen aatoksensa niin liiti, kun kuvat liittyivät vähitellen


kuviin, maat maihin, harjut harjuihin ja vuomat vuomiin
salmekkeiden kautta, kypsyi äkkiä hänen mielessään ajatus, jota hän
oli hautonut, mutta ei ennen jaksanut ratkaista.
Hänen päätöksensä oli selvä.

Se oli valiojoukko, joka hänen onnistui saada kokoon ja joka alkoi


peloittavana kierrellä Sallan ja Kurtin välimailla. Hän ei huolinut
joukkoonsa ketään, joka oli raihnainen tai huono, kenessä
kynnenkään vertaa velttoutta asui, se erotettiin armottomasti
joukosta. Tällainen eristäminen ei susien parissa ollut mitään väärää,
sati se vain koski täysi-ikäistä. Eräitten elukoitten parissa on asiat
toisin. Io-hui tiesi, että eräistä parvista ei poisteta joukosta ketään,
kuinka heikko ja vaivainen tuo olisikin, ei ketään saanut jättää
jälkeen. Ja saattoipa olla niinkin, että tullessaan voimakkaan väen
sekaan kokosi voimatonkin voimaa, pääsi kehnokin vähitellen
kehittymään. Mutta tästä oli paljon vaaraa väkeville, niiden yritykset
kävivät heikommiksi ja siitä saattoi koitua surmakin koko seurueelle.
Ylevämpää, valtavampaa oli hukkien mielestä, että se, joka jäljelle
jäi, omalla voimallaan tiensä uursi, omine yritteleväisyyksineen
eelleen kävi. Silloin se voima, minkä tämä heikko saavutti, oli
itsekoottua voimaa, eikä lainattua, oli todellista voimaa, mikä
koskaan ei voinut pettää eikä jättää mihinkään pinteeseen.

Tämä valiojoukko, jota Io-hui johti, joutui pian laajalti tunnetuksi,


se kierteli äärettömiä maa-aloja. Yhtenä päivänä sen jäljet nähtiin
Sallan alla ja seuraavana aamuna nähtiin 5-lukuinen parvi Lailla. Oli
kuin jokin erikoinen into tai riemastus olisi niitä edelleen ajanut.

Ja jokin niitä kiihoittikin menoon. Kun Io-hui esitti, että huomenna


oltaisiin tuolla, mistä aurinko nousee, niin sinne suuntausi matka;
kun Io-hui esitti, että nyt maattaisiin Sallan mutkan lepikossa, niin
laskeuduttiin länteenpäin auringon kera.

Io-huihin luotti jokainen. Nuo toverinsa, jotka olivat vanhoja,


luisevia korven mittaajia, kauhistuivat ja samalla riemastuivat Io-huin
mahtia. Kun he, lumen noustua metsässä kolmeen kyynärään,
ilmestyivät keskelle Ylikurtin kylää, silloin kun poromiehet juuri olivat
koolla, oli jokainen varma siitä, että loppu oli edessä. Ja kuitenkin he
seurasivat Io-huita sinne. Mutta kun ajo alkoi, niin he eivät voineet
olla kummastelematta, kun kulku kävi aavoja harjuja pitkin, vuomia
keskeltä poikki, metsiä keskeltä halki, järviä suoraan yli, miten lunta
oli matalalta ja miten pohja oli kova. Ennen tällaisten pyryjen jälkeen
vajosi mahaa myöten lumeen, sai kaaloa niin että kieli lunta uursi.
Nyt oli tuskin päälle nilkan lunta. Mikähän mahti tuossa oli, tuossa
Io-huissa.

Mikähän voima siinä oli.

He katsoivat häntä pelvolla, kun hän seisoi Njätintyngällä ja katseli


yli Kurttien, Mutta kun he näkivät hänen tupsunsa, joka olasta nousi
pörröisenä kohti taivasta, kun he näkivät hänen kaulansa suonen,
joka paksuna, pullistuneena kulki lavan edestä korvan juurta kohden,
sen, jonka kaulan vinous pudisti näkyviin, kun he näkivät hänen
kivenkovat jänteensä, jotka mahtavina sääriluita ympäröivät, kun he
oikein ymmärsivät hänen suuruutensa yli heidän, silloin he kohottivat
huudon, joka raikui kuin ylvästelevä mahtihuuto yli Kurtin ja
houkutteli lapset ja miehet portaille, he ulvoivat kiitosta Io-huille,
joka oli kaikkien olleitten ja tulevien susien valtias, jolla oli johtajan
valtikka.

Iäti, iäti sinua seuraamme, — jos meistä huolit!

Io-hui oli vaiti.

*****
Liikettä, kirjavaa eloa ja meurua oli Kelloselän kaarteella. Miehet
touhusivat kajahtavia huutoja päästellen, poikaset kahloivat
poljetussa lumessa heikompia poroja kokoillen. Vaikka uskalsivathan
he isonkin hirvaan sarviin suopungin sinkauttaa: heittäytyen
istumaan ja painaen vankat jalat syvälle lumeen hallitsivat he
jotakuinkin väkevimmänkin elukan. Ja hallit seurasivat tarkkaavaisina
poromiesten liikkeitä, he lopettelivat nyt vain jo ammoin sitten
alkamaansa työtä. Touhuten olivat he viikkokausia pitäneet tuota
häristelevää karjaa koolla, kyliä sivu, saloja halki olivat he sitä
saatelleet. Lyhyt sapara liikkumattomana olivat he karjan eli tokan
liikkeitä seuranneet, ettei se päässyt mitään säikähtämään ja
hajoamaan, pelkkä velvollisuuden tunto kiinnitti heidän kaiken
huomionsa.

Ja ehtihän sitä ihmisiä ajatella, kun kaikenlaiset nelin kontin


ryömivät sikiöt pahoin pitelivät tuvassa, tuota pahoinpitelyä, jota
vähän muristen kuitenkin niin mielellänsä sallii.

7000 poroa oli Kelloselän kaarteessa. Suopungit sinkoilivat jo


kolmatta päivää, ne takertuivat sarviin, ne kävivät kaulaan, ne
kietoutuivat jalan ympärille kuin solmittu. Ei auttanut petran vastaan
panna, ei auttaneet sen nelistämiset, ei maahan nujertuminen, ei
sekään, että takaperin kiskottiin, että kolmin jaloin täytyi loikata.
Katkesihan siinä väliin jalka. Mutta pahempi oli, jos merkkiä ei ollut
korvassa, tai jos merkki muuttui omistajan muuton kautta, silloin
punertui pää tulipunaiseksi, punaisia helmiä silloin lumeen tippuili, ja
saattoi tapahtua, että sama lumi muutamien päivien perästä koko
poronkin hautasi pehmoiseen vaippaansa.

Kaarteen karsinoissa, joita oli koko joukko, oli jo erotettuja poroja


suuret määrät, ja niitten luvut olivat karsinan suulla seisoväin
kirjaanpanijain tiedossa. Mutta kaarteen suulla oli toisenlainen seura:
siellä savu nousi, savu, jonka paljas näkeminen on korven kansan
riemu, minkä kaukaakin katsominen saa onnen tunteen mieleen,
siellä istui naisväkeä, joka höyryävää kahvia tarjosi. Kun tuli hikisenä
joukon touhusta, niin hyvälle maistui paukkuvana, valkeana päivänä
tuo musta tulikuuma juoma. Mutta neitosten silmät, jotka
kirkkaampina tavallistaan paloivat, saivat palaa päivän säteille ja
kinosten kiteille. Jos ne jonkun häikäisevätkin, hälveni tuo soaistus
heti, sillä poroja ei saanut kauan pitää koossa, kovin monta päivää
ne eivät ruoatta kaarteessa saaneet olla.

Korven Tuomas, joka kaarretta läheni, pysähtyi. Hän katseli tuota


hoilailevaa joukkoa, liikettä, juoksua, heittoja. Suopungit nousivat ja
lankesivat kuin tähdet sinä yhtenä yönä kerran. Mutta sitten hän
ajatteli muuta. Hänen ajatuksensa kietoi huomio, miten porojen
parvi oli käynyt surkeaksi. Harvoja vankkoja poroja, sellaisia, jotka
ennen halkoivat Lapin Teuravuoman muutamassa tiimassa, ei, ei
laisinkaan sellaisia. Tämä oli aivan uusi suku, heikko, seassahan oli
sellaisia että itketti, niin pieniä. Kummakos oli, kun jäkälä maassa oli
aivan lopussa. Täytyi koettaa, oliko tuo valkea vanuke, joka tuhkaksi
poljettua mannerta verhosi, oliko se todellakin jäkälää. Tai mitä
maan hometta se oli.

Hän aikoi kääntyä. Hän aikoi kääntyä koko tästä ihmiskunnasta,


joka surmasi ja sorti, joka metsät puhdisti ja järvet tyhjensi. Joka ei
antanut jäniksenkään lumihangella leikkiä, vaan ansoillaan pyyti ja
piinasi, joka ei antanut näädän nukkua rauhassa oravanpesässä,
vaan surmasi pyssyllään, joka pieniä pyitäkin, jotka pääsivät
kuusikoissa havukoita ja pöllöjä pakoon, naaki ja vaaniskeli. Ei, ei
tämä elämä ollut hänelle. Hän oli riekkojen ystävä, riekkojen, jotka
hänen portailleen tulivat, siellä missä hän asui, korkean
Kätkätunturin juurella, hän oli sotkien ystävä, jotka häntä tupaan
sisälle seurasivat, kun hän nousi sille järveltä, hän oli susien veli,
susien, joita ajettiin niinkuin ryöväreitä, kun he kulkivat niillä mailla,
jotka ammoin olivat yksin heille kuuluneet. Ei, hän aikoi kääntyä,
mutta silloin hänet nähtiin.

— Oon, on se Tuomas!

— Se, se on!

— Tuomas kaarteella!

— Korven Tuomas kaarteella!

Tervehdys on äänekäs; sitten alkaa kysely.

Mutta mikä viholainen on mennyt miehiin! Hyväkö tulos, rikas


vuosi miehet tekee niin ylimielisiksi? Sekö voima, minkä he ovat
koonneet porojen kanssa temmeltäessään, nyt purkautuu pilana
yhden miehen niskoille? Eikö heidän pitäisi hallita itseään, eikö
heidän pitäisi muistaa, kuka heillä on edessään, kuka nyt pitkistä
ajoista, laskee alas kylille, umpisuinen, ihmisiä karkkova mies,. Hullu-
Tuomas.

— Eipä ole vielä karhut tehneet paistia Korpi-Tuomaasta! kuului


muuan tervehdys.

— Jokos alkoivat hätyyttää, kun vaarat jätit? Parasta olisi pyssy


hankkia, ennenkuin ne ottavat pyssyn koparoihinsa.

— Eikös ne taloa tutkiskele, nosta nurkkaa ja kurkista sisälle, — —



— Mitäpä ne Tuomaan taloa kaataisi; pikemmin ne pönkitsee sitä.
Karhu kullakin sivulla.

— Soo, soo, pojat, antakaa rauhaa rehtimiehelle. Kahvia, vaari, se


ei ole eläinkunnan antimesta tehty,

— Näkyikö ahman jälkiä?

— No — no pysytään aisoissa.

Mutta poikaväki ja nuoret miehetkään eivät voi pysyä alallaan. Ne


kiusaavat tulokasta kertomalla hänelle koko riistan tapon kuluneena
syksynä, kaikki karhujen kaadot, porojen suuren annon. Sillä he
tietävät, että se on Tuomaalle tuskallista kuulemista. Lopulta Tuomas
vimmastuu. Nähdään, kuinka viha vähitellen alkaa kiehua
umpimielisessä, hän nousee ja alkaa huitoa käsiään.

— Jaa, näkyikö siellä näädän jälkiä?

—Näkyi siellä! Susien jälkiä.

Kaikki hätkähtivät. Sitten huutaa Pekka Aatsinki:

— Missä!

— Tuossa jänkän päässä. Joku-kymmen sauvan pisto kaarteelta.

— Oliko ne verekset?

— H-verekset? Susi seisoi sylen päässä.

— Hah-hah-haa, vai seisoi! Vai aikoo se Tuomas täyttä väkeä


huiputtaa.
— Susi täällä, susi täällä, kuului huuto ahteen alta. — Ajoporon
kaatanut — — —

— Missä

— — Kenen se on?

— Pekka Aatsingin — —

— Hullu Tuomas, vikisee Pekka Aatsinki, — nyt sen on loppu.

— Ei siitä ole sinulle, Pekka Aatsinki. Älä lähde sinne!

— Mitä!

— Älä lähde sinne. Et voita mitään. Ei voi sille mitään edes


Aatsinki.

— Mikä se on?

— Se on se, jolle ei voi mitään edes Pekka Aatsinki. Älä lähdekään


perään. Se on se, jota ennen Pekka Aatsinkikin kuolee.

Ja hän alkaa huitoa käsiään, ja hän vetää henkeä keuhkoihin, jotta


suhina kuuluu, hänen katseensa lentää hurjana yli kaarteen. Ja
heittäen pitkässä kaaressa kätensä, osoittaen ikäänkuin yli koko
maan, yli Sallan, yli Kurtin, yli Karhun, kauas, kohden pohjoista hän
huutaa;

— Se on — Vinokaula!

Neljä miestä lähtee liikkeelle, neljä sitkeintä. Muiden on turha


yrittääkään, liian monta miestä on jo Vinokaula kuoloa lähelle
rasittanut. Lähtijät heittävät heti peskit ja iislantilaiset paidat
päältään.

Kolmen päivän kuluttua palaa kolme takaisin.

— Ei hellittänyt, sanoivat he. Ei hellittänyt Pekka Aatsinki.

Mutta nuo kolme miestä olivat ne, jotka viimeksi näkivät Pekka
Aatsingin elossa.

*****

Noiden kolmen miehen kertomus osoittaa erään suurimpia kilpoja,


mitä on tapahtunut ihmisten ja eläinten välillä.

He kertoivat, mitä äärettömiä aloja he olivat samoilleet, miten


matka oli jatkunut, yhä edelleen, yhä edelleen. ——vaaran he olivat
sivuuttaneet, ——vuoman olivat kulkeneet päästä päähän. Tiima oli
liittynyt tiimaan, jalat alkoivat väsymyksestä nuljahdella, hiki tihkui
kuin rämeestä vesi. Tavan takaa näkivät he suden; saapuessaan
jollekin isommalle rämeelle näkivät he sen mennä viillettävän,
ravakasti, syvässä lumessa puhkuen. — — Toisena iltapäivänä he
päättivät lopettaa ajon. Ruuatta ei ollut hauska ajeskella, kelikin oli
raskas, jo kyllin monasti oli sama hukka heitä pettänyt, niin että
suunnan muuttuessa Kurtin pohjoispuolelta itään he erkanivat
ajosta.

Monasti he olivatkin antaneet väsymyksestä ylön.

Mutta suden sitkeydestä heillä ei ollut kyllin kiitosta. Sen


nerokkuutta he eivät voineet kyllin ihmetellä, niin erinomaisesti se
osasi valita juoksemansa seudut, valita maat, missä oli vähän lunta.
Sen edistymistä kolmattakyynäräisessä pehmeässä lumessa, yhä
kolmen päivän lumentulon jälkeen, he eivät voineet kyllin
kummastella. Nuo hiihtäjät eivät tienneet, että pohja, jolla susi kulki,
oli kova, että nämä matkat, joita myöten suunnattiin, olivat useaan
kertaan poljettuja, olivat Io-huin joukon valmistamat. Sillä Io-huin
juoksu oli erikoinen; se rämpi niin lumessa, että tottunut
poromieskin luuli, että siinä eistyminen oli vaatinut mitä ankarimpia
ponnistuksia, ja tavantakaa oli susi painanut vatsansa lumeen, niin
että näytti siltä, kuin se olisi puolta selkää myöten kahlonut.

Pekka Aatsinki jatkoi ajoa. Pekka Aatsinki tahtoi näyttää, että vielä
oli Ihmisellä mahti yli luomakunnan, että mitä hän lupasi, sen hän
myös täytti. Hän ei aikonut tulla ilman taljaa, — kävipä sitten miten
kävi.

On turha selitellä tämän kilvan kaikkea kauheutta, sitä ei sanat


pysty kuvailemaan. On turha selitellä, miten kaikki murtava raukeus
äkkiä luihin ja ytimiin valahti, mutta miten se vähitellen taas haipui,
kohottaakseen miltei kaksinkertaiseksi voiman. Miten kilvassa aavalla
pistos alkoi viiltää kylkeä, mutta tyyntyi jonkun hetken maannista
kylmällä lumella.

Ajo vain kävi edelleen.

Io-hui oli vankempi kuin koskaan ennen, vankempi kuin itse oli
luullutkaan. Hän kompuroi reippaasti eteenpäin, viskoen
etukäpälillään lunta ylös sivuille. Neljäs iltapäivä oli jo käsissä.

Laajalla rämeellä oltiin, siellä täällä harva männyntöriläs katkaisi


taustalla olevan metsän juovan. Oli miltei tyyni, ja haaleaa.

Mutta mitä? joko loppuisi ajo, hätkähtää Io-hui. Joko Pekka


Aatsinki viivähtää. Joko — — —.
Ei, hänen täytyy hiljentää vauhtia, hän alkoi hoiperrella; lopettaa
tähän ei ajoa saanut.

Totta tosiaan hän alkoi jäädä.

Rämemännyt yksinäisinä katselivat ja ikäänkuin huojuilivat, kun


Io-hui pani pitkälleen. Hän antoi Pekka Aatsingin tulla vähän
lähemmäksi, lähti hiljaa etenemään.

Hän näki, kun pyssy ojentui.

Hän pani pään selän suojaan varmuuden vuoksi:

— Ampukoon vain, — noin kaukaa.

Jokin vihlasi hänen selkäänsä vasemmalta lavalta, erämaa


pamahti.
Io-hui oli horjahtavinaan kyljelleen syvälle lumeen.

Aatsinki hätkähti:

— Jo kävi.

Mutta Io-hui nousi, kaatui taas, nousi, juoksi ja kaatui. Juoksi


muutaman sylen ja kaatui. Syvä kuoppa lumessa osoitti, mihin se oli
kaatunut.

Silloin vasta alkoi hurjin ajo.

Viimeiset voimat pantiin liikkeelle. Hoiperrellen, myötään susi,


väliin mieskin, siinä kuljettiin vuomia, vuomia, vuomia, nyt ei menty
kankaille. Tunti liittyi tuntiin.

— Ei mene kauas, mutisi Aatsinki.


Mutta matkaa jatkui, matkaa jatkui. Oli kuin taas olisi voimat
lisääntyneet.

Tultiin metsään, lumi syveni.

— Viime voimat, ajatteli Aatsinki. — Korpeen kuolemaan.

Noustiin kankaalle. Näki heti, että lumi alkoi syvetä, kun metsään
tultiin — hourasiko jo Aatsinki. Puolitiehen puita, niin syvää. Mahtoi
olla pohja syvällä. Ja leppoisaa ja pehmeää oli lumi.

Hän kokosi jälleen voimansa ja painoi metsään.

Näin kului jälleen joku hetki.

Ei hellitä vähällä.

Mutta mitä: metsä loppuu, maa nousee.

Mitä ihmettä.

Huimaako päätä, vai nouseeko maa, — nousee.

Kyllä se nousee. Se nousee kuin pilvi ylöspäin, se häikäisee silmiä,


paljas lumimeri edessä levenee. Ja se nousee, nousee.

Mitä järjettömyyttä sudelta lähteä aavalle, nousta tunturille.

Pekka Aatsinki kapuaa ylöspäin. Hän tuntee, että hänen täytyy


nousta, nousta korkealle, niin korkealle kuin mahdollista, nousta
ylöspäin, kuin pilven laitaa, irti maasta, irti metsästä, kohti korkeutta.

Ja hän kapuaa, hiki helmiää, matka etenee. Hän saapuu laelle.


Susi on hävinnyt.

Kuinka raikas onkaan tuuli, joka puhaltaa vastaan hänen


päästyänsä laelle, kuinka viilentääkään se rintaa.

Täytyy avata paita.

Silloin on kuin Pekka Aatsinki irroittuisi maasta, niinkuin hän kävisi


niin keveäksi, että hän lentäisi ylöspäin, taaksepäin, selälleen, katse
luotuna pehmoisiin pilviin, jotka erämaan päällä liitelevät, ja hän
levittää kätensä ja nousee, nousee, — kohti korkeutta — — —

*****

Samoinkuin Sallatunturi vallitsee Sallan ympäristöä, samoin


vartioipi muita ylempänä, yhtä yksinäisenä, ikäänkuin omaa
yksinäisyyttään peläten, Karhutunturi omaa ympäristöään. Mutta
yhtä monelta taholta kuin metsänkävijän silmälle Salla näyttää
paistavan, väliin sieltä, väliin täältä, yhtä varmana seisoo Karhu juuri
paikallaan. Tällä Karhutunturilla on laki tallattu aivan tasaiseksi.

Oletteko nähneet jäkäläkangasta, jolla porot ovat useita päiviä


asuneet, jolla ei polkematonta kohtaa ole. Oletteko nähneet toria,
kun markkinat ovat loppuneet ja kojut, laatikot ja muu roju korjattu
talteen. Oletteko nähneet lehtopilkkaa, missä jäniksille — yläkuuhun
— on kaadettu haapa.

Silloin ymmärrätte, miten Karhutunturin laki on tallattu.

Korven oli tahtonut voittaa Pekka Aatsinki. Hän kulkikin korven


ohitse —.
Korkealla Karhutunturilla, joka vallitsee laajaa erämaata, joka
yksinään, mahtavana seisoo uljuudessaan sitten maailman alun, —
hän lepäsi.

Saiko häneen kukaan kajota, saiko hiuskarvaa liikuttaa. Eikö häntä


oltu juhlittu, eikö ulvonta ollut kuulunut kauas ihmisten asunnoille.

Luuletteko, että korpi ei anna arvoa Voimalle, ettei se osaa ylistää


Ylhäyttä? Luuletteko, että voitettua Mahtia saa häväistä.

Ei kukaan, ei kukaan saa siihen koskea.

*****

On aamu. Kirkkaana kuin kulta säteilee aurinko taivaalta. Erämaa


humisee. Tuulen henkäykset pelmuavat pensaissa.

Mutta katsokaa! katsokaa sutta, joka kuvastuu vasten säihkyvää


taivasta sen seistessä tunturin laidalla. Katsokaa kaulaa, kuinka
vinona se kaartuu.

Seuratkaa katseensa suuntaa, mihin se vie.

Nuorttiin.

Io-huin aatos irtaantuu ja lähtee lentämään. Tuota tuttua matkaa,


jota se niin monta kymmentä kertaa ennen on liitänyt, se lentää, se
halkoo maita, se puhkoo metsiä. Se saapuu perille. Kimmeltävänä
kuin tulimeri leviää avara, luminen erämaa hänen eteensä. Ihmisten
palaavat raitiot sitä vain halkovat, muuten ei mikään sen rauhaa
häiritse. Riekot tekevät kummallisia teitään katajasta toiseen,
rämeiltä maille ja päinvastoin. Näädät hyppivät pitkin lumikenttiä,
puista toisiin kavuten. Ahmat polkevat vankkoja uriaan metsiin. Siellä
täällä kohoaa karhu lumen alta. Io-hui saa levähtää jälleen; hän saa
lepuuttaa rauenneita jäseniään Kuorvun harjulla ja antaa päivän
paahtaa selkäänsä. Hän saa korvauksen vaivoistaan.

Hänen päänsä vaipuu etukäpälien väliin. Vihdoin, kohti Nuorttia,


kohti
Nuorttia.

Hän liukuu päälleen alas kiveltä.

Hän ei liiku enää.


ROMANTTINEN KAIPAUS.

E. A. Saarimaa.

"On kaipaus rinnassa mulla, en tiedä sen maalia vaan. Ei


liene se siinto kauniin maan eikä pilvien puuntokaan.

Ei liene se pauhina maailman, ei haudan rauhakaan. On


kaipaus vuoksi kaipauksen, olen luotu kaipaamaan."

Nämä erään ruotsalaisen runoilijan sanat luonnehtivat hyvin


romantiikkojen ikuista ikävää, josta he eivät tiedä, mistä se tulee ja
mikä sen määrä on. Tämä kaipaus on kaiken runouden syvimpiä
lähteitä. Mutta se kuuluu erikoisesti romanttisille runoilijoille. Kun
romantiikka noin 1800:n tienoilla tulee erikoiseksi suunnaksi ja
liikkeeksi Euroopan kirjallisuudessa, on kaipaus se sana, joka
ilmaisee koko tämän suunnan pohjan ja olemuksen. Eräs sen ajan
saksalainen romantikko sanoo verratessaan toisiinsa kukkaa ja
ihmishenkeä niiden välisen eron olevan siinä, että kukka ei voi
kaivata, vaan ainoastaan kasvaa.

Romantikon kaipaus johtaa siihen, että todellisuus ja nykyisyys ei


häntä tyydytä. Muistot ja toiveet ovat hänelle rakkaammat, niistä

You might also like