Click here to Skip to main content
15,895,746 members
Articles / Desktop Programming / MFC
Article

What's New in ACF 0.4

Rate me:
Please Sign up or sign in to vote.
3.60/5 (6 votes)
10 Oct 20043 min read 28.3K   11  
This article describes what's new in ACF (Another C++ Framework) version 0.4.

Introduction

ACF (Another C++ Framework) is a C++ framework designed to bring the power and RAD of the .NET framework to standard C++. ACF version 0.4 added/updated the following features:

1. Simple XML reading and writing

ACF 0.4 supports simple XML reading and writing via XmlTextReader and XmlTextWriter classes, which are core XML reading/writing classes in the .NET framework.

XmlTextReader

XmlTextReader provides fast, forward-only XML reading functionality. The Read method advances the reader to the next node (element, text, etc.), and the properties (e.g. Name, Value) reflect the value of the current node.

For example, given the following XML file (test.xml):

XML
<?xml version="1.0"?>
<!-- This is a sample XML document -->
<book>
  <title>XML Developer's Guide</title>
  <author>Gambardella, Matthew</author>
  <price>44.95</price>
  <description><![CDATA[An in-depth look at creating applications with XML, 
  using <, >,]]> and &.</description>
</book>

The following code reads the XML file and writes the nodes to console:

#include <AcfCorlib.h>
#include <AcfXml.h>

using namespace Acf;
using namespace Acf::Xml;

int main() {
    XmlTextReaderPtr reader = new XmlTextReader(str(L"test.xml"));
    reader->set_WhitespaceHandling(WhitespaceHandling::None);

    // Parse the file and display each of the nodes.
    while (reader->Read()) {
        switch (reader->get_NodeType()) {
        case XmlNodeType::XmlDeclaration:
            Console::Write(L"<?xml version='1.0'?>");
            break;
        case XmlNodeType::ProcessingInstruction:
            Console::Write(L"<?{0} {1}?>", reader->get_Name(), 
                                                     reader->get_Value());
            break;
        case XmlNodeType::Comment:
            Console::Write(L"<!--{0}-->", reader->get_Value());
            break;
        case XmlNodeType::CDATA:
            Console::Write(L"<![CDATA[{0}]]>", reader->get_Value());
            break;
        case XmlNodeType::Element:
            if (reader->get_IsEmptyElement())
                Console::Write(L"<{0} />", reader->get_Name());
            else
                Console::Write(L"<{0}>", reader->get_Name());
            break;
        case XmlNodeType::EndElement:
            Console::Write(L"</{0}>", reader->get_Name());
            break;
        case XmlNodeType::Text:
            Console::Write(reader->get_Value());
            break;
        case XmlNodeType::EntityReference:
            Console::Write(reader->get_Name());
            break;
        }
    }

    return 0;
}

Internally, XmlTextReader uses a linked list to store the parsed nodes. The following diagram will help you understand how it works.

Image 1

There is also a sample application (XmlEditor) which shows how you can use multi-threading and XmlTextReader to build an interactive document outline. The document outline refreshes in real-time while typing, and when you click a node in the document tree, the corresponding element will be highlighted in the source editor.

Image 2

XmlTextWriter

XmlTextWriter provides fast, forward-only XML writing functionality. For example, the following code writes the sample XML to console:

XmlTextWriterPtr writer = new XmlTextWriter(Console::get_Out());
writer->set_Formatting(Formatting::Indented);

writer->WriteStartDocument();
writer->WriteComment(str(L" This is a sample XML document "));

writer->WriteStartElement(str(L"book"));
writer->WriteElementString(str(L"title"), str(L"XML Developer's Guide"));
writer->WriteElementString(str(L"author"), str(L"Gambardella, Matthew"));
writer->WriteElementString(str(L"price"), str(L"44.95"));
writer->WriteStartElement(str(L"description"));
writer->WriteCData(str(L"An in-depth look at creating applications 
                                           with XML, using <, >,"));
writer->WriteString(str(L" and &."));
writer->WriteEndElement();
writer->WriteEndElement();

writer->WriteEndDocument();

Please refer to MSDN for detailed description on XmlTextReader and XmlTextWriter classes.

2. Threading update

Thread Local Storage (TLS)

ACF 0.4 supports thread local storage (TLS), which is a mechanism to store data that is unique to a thread. To use TLS, first call Thread::AllocateDataSlot to allocate a new data slot and then use Thread::GetData/Thread::SetData to get/set data. Following is an example:

#include <AcfCorlib.h>

using namespace Acf;
using namespace Acf::Threading;

LocalDataStoreSlotPtr _slot = Thread::AllocateDataSlot();

static void ThreadProc() {
    ObjectPtr obj = Thread::GetData(_slot); // obj == null
    Thread::SetData(_slot, box(10));
}

int main() {
    // Main thread
    ObjectPtr obj = new Object();
    Thread::SetData(_slot, obj);

    // Worker thread
    ThreadPtr thread = new Thread(ThreadProc);
    thread->Start();
    thread->Join();

    return 0;
}

The TLS implementation in ACF is straightforward and platform-independent: each Thread object holds an instance TLS map, which stores TLS data. This can be illustrated as follows:

class Thread : public Object {
    RefPtr<Dictionary<LocalDataStoreSlot*, ObjectPtr> > _tlsObjects;

    static LocalDataStoreSlotPtr AllocateDataSlot() {
        return new LocalDataStoreSlot();
    }
    static ObjectPtr GetData(LocalDataStoreSlot* slot) {
        ThreadPtr thread = Thread::get_CurrentThread();
        ObjectPtr value = null;
        thread->_tlsObjects->TryGetValue(slot, &value);
        return value;
    }
    static void SetData(LocalDataStoreSlot* slot, Object* value) {
        ThreadPtr thread = Thread::get_CurrentThread();
        thread->_tlsObjects->set_Item(slot, value);
    }
};

ThreadPool

ACF 0.4 supports ThreadPool, which is an easier way to use multiple threads for some tasks. Following is an example:

#include <AcfCorlib.h>

using namespace Acf;
using namespace Acf::Threading;

static void DoWork(Object* state) {
    String* s = ref_cast<String*>(state);
    Console::WriteLine(s);
}

int main() {
    for (int i = 0; i < 3; i++) {
        ThreadPool::QueueUserWorkItem(DoWork, 
            String::Format(L"Hello from work item {0}.", str(i + 1)));
    }

    // We need this because ThreadPool uses background threads, which 
    // do not keep the application running
    Thread::Sleep(1000);

    return 0;
}

The ThreadPool implementation in the CLR is very complex. However, in the .NET compact framework, the ThreadPool implementation is quite simple: the ThreadPool class just creates a System.Threading.Timer to execute each worker delegate asynchronously, and there is no thread management at all. In ACF 0.4, the ThreadPool implementation uses the timer approach for simplicity, however, this may be changed in future releases.

3. Other updates

ACF 0.4 supports date time formatting (parsing is not supported yet). The following sample application shows the standard formats and custom formats:

Image 3

There are also other updates, for example, delegates and the Queue<T> class. ACF 0.4 also removed Visual C++ specific language features, for example, properties, which means p->Text is now p->get_Text(). Portability (platform, compiler) will be addressed in future releases.

How to use

  • Download and unzip the source files (say C:\acf).
  • Setup include and library directories in Visual Studio (requires Visual C++ 2003 or higher).
    • Include: C:\acf\src\Corlib and C:\acf\src\Xml.
    • Library: C:\acf\lib.
  • Open C:\acf\src\acf.sln and build (you can choose debug, release or both).
  • Now, it's ready to build other samples or your applications.

Project development

I started this project several months ago with the wish to make it a useful and successful open source C++ framework, and got some good feedback since then. However, it turns out that it's hard for me to keep this project alive and health, mainly because I'm not quite familiar with CVS and Internet-based collaboration, and in recent months I've been busy and don't have good network access. If you are interested in this project, and are familiar with open source project development, please help with this project. Thanks. Suggestions and feedback are also welcome.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
China China
Yingle Jia is a software engineer located in Beijing, China. He currently works at IBM CSDL (China Software Development Lab). His interests include C++/COM/C#/.NET/XML, etc. He likes coding and writing.

He is the creator of ACF (Another C++ Framework) project. See http://acfproj.sourceforge.net/.

He also has a blog at http://blogs.wwwcoder.com/yljia/

Comments and Discussions

 
-- There are no messages in this forum --