Free Essay

Computer Science C++

In:

Submitted By toluoralusi
Words 6570
Pages 27
Special Report Bundle

C++Ox: The Dawning of a New Standard

Contents

C++0x: The Dawning of a New Standard

It's been 10 years since the first ISO C++ standard, and 2009 will bring us the second. In this special report, DevX delves into the new features being discussed by the standards team. Learn how these new features will revolutionize the way you code.

Overview: C++ Gets an Overhaul

It's been 10 years since the first ISO C++ standard, and 2009 will bring us the second. Learn about the new features being added and how they will revolutionize the language.

Easier C++: An Introduction to Concepts

C++0x concepts bring the full power of the Generic Programming paradigm to C++, making templates more expressive, easier to write, and easier to use. Spectacularly poor template error messages are a thing of the past!

Simpler Multithreading in C++0x

The new standard will support multithreading, with a new thread library. Find out how this will improve porting code, and reduce the number of APIs and syntaxes you use.

The State of the Language: An Interview with Bjarne Stroustrup
C++ founding father assesses the language on the eve of its new standard.

Timeline: C++ in Retrospect

From its nascent pre-processor in 1979 to today's incredibly sophisticated language features and libraries, we've documented each step along the way.

C++0x: The Dawning of a New Standard

Overview: C++ Gets an Overhaul

Overview: C++ Gets an Overhaul

C++Ox: The Dawning of a New Standard

Originally from http://www.devx.com/SpecialReports/Article/38884

Overview: C++ Gets an Overhaul
In this overview of the changes proposed for the new standard, you'll get an idea of the kinds of improvements you can expect this time around. by Danny Kalev

en years after the ratification of the first ISO C++ standard, C++ is heading for no less than a revolution. C++0x, the new C++ standard due in 2009, brings a new spirit and new flesh into the software development world. Brace yourself for state-of-the-art design idioms, even better performance, and a plethora of new features such as multithreading, concepts, hash table, rvalue references, smarter smart pointers, and new algorithms. No doubt you'll find a lot to like in C++0x! New Core Features The two most important features of C++0x are concepts and concurrency support. Concepts enable programmers to specify constraints on template parameters, thus making generic programming and design immensely simpler and more reliable (see Douglas Gregor's excellent introduction to concepts). Variadic templates, template aliases (also called template typedefs), and static_assertthough not directly related to conceptswill also make the use of templates in generic libraries more intuitive, flexible, and less error prone. The importance of a standardized concurrency API in C++ can't be overstated: As multicore processors are becoming widespread, you simply can't afford to remain stuck in the singlethreaded era, or compromise on platform-dependent APIs. At last, there's a portable, standardized and efficient multithreading library for C++. To get a glimpse of the new concurrency facilities of C+ +0x, you're welcome to read Anthony Williams' brilliant introduction to multithreading in C++0x. You can find additional info about thread-local storage here. Rvalue references are yet another silent revolution. While most users will probably not even know they exist (read my interview with Bjarne Stroustrup), rvalue references enable library designers to optimize containers and algorithms by implementing move semantics and perfect forwarding easily, thus reducing unneeded copy operations.

Overview: C++ Gets an Overhaul

Automatic type deduction is made possible by the new keywords auto and decltype which deduce the type of an object from its initializer and capture the type of an expression without having to spell it out, respectively. Adding auto and decltype also paves the way for a new function declaration syntax. The function's return type appears after the -> sign:

auto func(int x)->double {return pow(x);}
Lambda expressions and closures are another prominent feature of C++0x. A lambda expression is a nameless function defined at the place where it's called. It is similar to a function object except that the programmer is rid of the burden of declaring a class with a constructor, defining an overloaded () operator and an instantiating a temporary object of that classthis tedium now becomes the compiler's job. Here's an example of a lambda expression:

//a lambda expression is used as an argument myfunc([](int x, int y) -> int {return x+y;} )
The lambda expression is indicated by the lambda introducer [] followed by a parameter list in parentheses. The optional return type comes next, following the -> sign. Finally, the lambda block itself is enclosed in braces.

Convenience Features Some C++0x features are meant to simplify recurring programming tasks and minimize boilerplate code. Most of these "convenience features" were borrowed from other programming languages. These convenience features include:
● ● ●

A null pointer literal called nullptr Strongly-typed enumerations Delegating and inheriting constructors

Listing 1 demonstrates these features. C++0x also removes some embarrassments from the language. For example, C++03 has at least three different forms of initialization:

int x=0; int x(0); int y[2]={1,2};
C++0x defines a unified initialization notation which can even be used in the declaration of dynamically allocated arrays:

Overview: C++ Gets an Overhaul

int* a = new int[4] {1, 10, 20,95 }; vector vs={"ab","cd","ef"}; class S { int arr[3]; public: S() : arr{ 1, 2, 3 } {} };
More Control in Your Hands Certain new core features are meant to provide a standardized and uniform mechanism for controlling the compilation and execution environment programmatically. For example, take memory alignment. In C++03, you have to resort to compiler-dependent, non-portable hacks if you want to override the default alignment of your data. C++0x introduces two new operators: alignof and alignas that query and override the alignment requirements of your data, respectively:

alignas (16) class Session { long long timestamp; int authorizations; bool active; //... }; cout' operator exists. Therefore, the template author is bound by the same contract as the user, and there cannot be any surprises where the template author states one requirement in the contract but uses a slightly different operation in the implementation. This is exactly the kind of problem that occurs with template libraries today: Because most types that max() would be tested with will have both less-than and greater-than operations, the latent errorthat the function requires less-than but uses greater-thanis unlikely to be detected by testing. With concepts, however, the compiler detects this form of error immediately. Because both the template author and user are held to the same contract, the compiler can provide an extremely important guarantee: If both the template's implementation and the use of the template meet the contract's requirements, the instantiation of that template will not fail. There are two practical effects to this guarantee. First, concepts eliminate the spectacularly poor error messages produced by long instantiation backtraces, because the failures occur before template instantiation is even attempted. Second, both users and library authors can have a far greater level of confidence in template libraries using concepts than in the corresponding pre-concept libraries, because the compiler takes a more active role in verifying the correctness of templates. The Perimeter of a Polygon Listing 2 contains a simple algorithm that computes the perimeter of the polygon it is given, by summing the lengths of each of the sides of the polygon. Polygons are described by the Polygon concept, which provides functions that determine the number of sides and the length of a given side. The Polygon concept's requirements can be satisfied by many different data types. For example, you can implement a simple triangle class that can be passed to the perimeter() function:

class triangle {

Easier C++: An Introduction to Concepts

public: int sides[3]; }; int num_sides(const triangle& tri) { return 3; } int side_length(const triangle& tri, int index) { return tri.sides[index]; } concept_map Polygon { }
The triangle class provides the operations required by the Polygon concept, num_sides() and side_length(). Note, however, that while the Polygon concept expects side_length() to return a double, triangle's version of side_length() returns an int. This is not an error. Concept maps provide one level of conversions, which will automatically convert the int returned by triangle's num_sides() into the double expected by users of the Polygon concept. This way, minor mismatches in the interface between the template user and the template author are resolved automatically in the concept map, making constrained templates more widely applicable.

Associated Types The implementation of perimeter() works with the triangle class, but it is suboptimal; despite the fact that the sides of the triangle are specified in terms of integers, all of the computation in perimeter() is performed via floating-point arithmetic. To solve this problem, the algorithm should instead perform the computation using the same type that the polygon uses to express the lengths of its sides, which may vary from one type to another. Concepts provide a way to express such types, which vary from one use of a concept to another: associated types. Associated types are declared within the body of a concept via the typename keyword (using the same syntax as template type parameters), and can be used to describe operations within the concept. You can now revise the Polygon concept to introduce an associated type named length_type, which is used to express the length of a single side in the polygon, and therefore is the return type of the side_length() operation:

concept Polygon { typename length_type int num_sides(const P&); length_type side_length(const P&, int index); }
Because the types of concept operations are important wherever the concepts are used, you can refer to an associated type as a nested type within the concept. For example, an updated perimeter() algorithm should refer to the length_type of the Polygon concept explicitly, rather than using double:

Easier C++: An Introduction to Concepts

template requires Polygon Polygon::length_type perimeter(const P& poly) { Polygon::length_type sum = 0; // error! for (int i = 0; i < num_sides(poly); ++i) sum += side_length(poly, i); // error! return sum; // error! }
Here, the uses of double are replaced with Polygon::length_type, which has made the algorithm capable of handling different length types, and therefore more reusable. However, this change has introduced some new errors that will be detected by the compiler. Previously, the algorithm was relying on the built-in operations provided by double: construction from an integer, addition via +=, and copy-construction of the return value. With an arbitrary length_type, you can no longer assume that all of these operations are available. They have to be specified as requirements on the length type, which the user's length type must satisfy. Member-Function Requirements To express the length type's requirements, we introduce another new concept, Numeric. The Numeric concept provides the essential operations required to sum a value:

auto concept Numeric { T::T(const T&); // copy construction T::T(int); // construction from an int T::~T(); // destructor T& operator+=(T&, const T&); // addition }
The first three operations in the Numeric concept require a copy constructor (which can be satisfied by a built-in initialization), the ability to construct a value of type T from an int, and the ability to destroy an object of type T. Each of these operations is stated using member function syntax with the T:: prefix, specifying that these operations apply to objects of type T. The same syntax can be used to describe specific member functions requirements (for example, T::clone()). Armed with the Numeric concept, you can express the perimeter() algorithm's full requirements as:

template requires Polygon && Numeric Polygon::length_type perimeter(const P& poly);
The "&&" in the requires clause states that both requirements must be satisfied for the algorithm to be usable, that is, the type P must be a Polygon and its length_type must be Numeric. Any number of different requirements can be added to a template using "&&", including multiple

Easier C++: An Introduction to Concepts

requirements on the same types.

Associated Requirements Adding the Numeric requirement to the perimeter() concept is correct, but it is not ideal. The requirement that the length_type of a Polygon be Numeric isn't solely a property of perimeter(): It's a more universal property that polygons only make sense if their length types are proper numeric types. To support this common usage, concepts support associated requirements, which specify extra requirements on the associated types of a concept within the concept body. Here is the final version of the Polygon concept, which makes use of associated requirements:

concept Polygon { typename length_type; requires Numeric; int num_sides(const P&); length_type side_length(const P&, int index); }
With this change, you can remove the explicit Numeric requirement from the perimeter() algorithm, because the length type of a Polygon is always numeric. For the final declaration of this perimeter () algorithm, I've also employed two syntactic shortcuts, which simplify the expression of template requirements and simplify access to associated types:

template

P::length_type perimeter(const P& poly);
The first shortcut is the use of Polygon P, which states that P is a template type parameter whose requirement is Polygon; it is identical to writing the same requirement within a requires clause. The second shortcut is the use of P::length_type, which searches for an associated type named length_type within the requirements placed on P, and is identical to Polygon::length_type. Syntax Remapping with Concept Maps All the concept maps so far have had empty bodies within their curly braces, and have been used to state (and check) that a type meets the concept requirements. However, concept maps need not be empty: they can contain definitions that specify how a type meets the concept requirements, and can even contain new functions that allow one to map the syntax provided by a type to the syntax expected by the concept. For example, start with a simple rectangle structure:

struct rectangle { double left, top, right, bottom; };

Easier C++: An Introduction to Concepts

You could add appropriate num_sides() and side_length() functions to this type to make it look like a Polygon. But, this expands the interface in a way that might not be desirable if the only purpose is to use the perimeter() function. Instead, you can write a concept map that makes the rectangle look like a polygon:

concept_map Polygon { typedef double length_type; int num_sides(const rectangle&) { return 4; } double side_length(const rectangle& rect, int index) { return index % 2? fabs(rect.right – rect.left) : fabs(rect.bottom – rect.top); }

}

In this concept map, the Polygon concept's requirements are satisfied by the body of the concept map itself. The functions provided by the concept map are visible only through the concept itself, and are not part of the public interface of the rectangle structure (which has not changed). Only those constrained templates that operate on Polygons will see this particular view of the rectangle structure. Through this syntax-remapping mechanism, an existing type can be adapted to meet an existing concept's requirements without changing either the type or the concept, allowing far greater reuse of generic algorithms than is possible without concept maps.

Concept Refinement and Concept-Based Overloading It is often the case when implementing a generic algorithm that there are several possible implementations, each of which involves different trade-offs. Some implementations may apply to a wide variety of data types (are very generic) while others operate more efficiently on a more narrow range of data types (are more specialized). For example, the generic perimeter() algorithm operates on any polygon in linear time, but there is a more efficient implementation: If you know that the polygon is an equilateral polygon (where all sides have the same length), you could compute the perimeter with a single multiplication. Like Polygon, EquilateralPolygon is a concept that describes types that behave like polygons. You could implement an EquilateralPolygon separately from the Polygon concept, but doing so misses an important opportunity for reuse, because every equilateral polygon is also a polygon. You can therefore express EquilateralPolygon as a refinement of the Polygon concept:

concept EquilateralPolygon : Polygon { }

Easier C++: An Introduction to Concepts

As the syntax implies, concept refinement is similar to concept "inheritance," because the refining concept (EquilateralPolygon) inherits all of the base concept's requirements (Polygon). Additionally, a type that is an EquilateralPolygon can be used in any algorithm that expects a Polygon, meaning that this square class could be used with the existing perimeter() algorithm:

class square { public: int length; }; concept_map EquilateralPolygon { typedef int length_type; int num_sides(const square&) { return 4; } int side_length(const square& sq, int) { return sq.length; }

}

Concept refinement describes a hierarchical "is-a" relationship that can also be used by conceptbased overloading, which involves overloading constrained templates on their requirements. As noted before, you can write a constant-time algorithm for computing the perimeter of an equilateral polygon, assuming you've already added a suitable multiplication operator to the Numeric concept:

template P::length_type perimeter(const P& poly) { return num_sides(poly) * side_length(poly, 0); }
This implementation of perimeter() overloads the previous, Polygon-based implementation. For types that are non-equilateral Polygons, the previous (linear-time) implementation will be used, because this (constant-time) constrained template's requirements will not be satisfied. For equilateral polygons like square, both implementations are valid because every equilateral polygon is a polygon. In this case, concept-based overloading picks the overload corresponding to the more refined concept, automatically selecting the constant-time implementation of perimeter(). Concept-based overloading (and, related, concept-based partial specialization of class templates) allows the user to provide multiple, different variations of the same algorithm, which differ only by the properties of the types that they support, and the compiler will select the most appropriate algorithm variation for each call site. Truly Easier C++ Concepts are a significant extension to the C++ template system. By allowing template authors to explicitly describe the template requirements, the compiler is able to verify both the template author’s and the template user's side of the (previously implicit) template contract. This additional

Easier C++: An Introduction to Concepts

type checking makes it easier to write templates (because they cannot violate the stated contract) and use templates (because contract violations result in far more readable error messages). The use of template requirements also enables advanced features that make templates more reusable, such as the ability to remap syntax within concept maps, and more expressive, through the use of concept-based overloading. As of this writing, concepts are expected to be included in the C++0x language and standard library. However, concepts have not yet been voted into the working paper by the ISO C++ standards committee, and some small details may still change. Watch for more interesting developments in C++0x and the concepts mechanism. Douglas Gregor is an active member of the ISO C++ committee, where he has lead the development and specification of various C++09 features, including concepts and variadic templates. A long-time contributor to Boost, Doug has developed several Boost libraries and acts as a moderator for the Boost community. Doug is currently the assistant director of the Open Systems Lab at Indiana University, where his research involves generic programming, parallel programming, and large-scale graph analysis.
DevX is a division of Jupitermedia Corporation © Copyright 2007 Jupitermedia Corporation. All Rights Reserved. Legal Notices

C++0x: The Dawning of a New Standard

Simpler Multithreading in C++0x

Simpler Multithreading in C++0x

C++Ox: The Dawning of a New Standard
Originally from http://www.devx.com/SpecialReports/Article/38883

Simpler Multithreading in C++0x
The new standard will support multithreading, with a new thread library. Find out how this will improve porting code, and reduce the number of APIs and syntaxes you use. by Anthony Williams

ne major new feature in the C++0x standard is multi-threading support. Prior to C++0x, any multithreading support in your C++ compiler has been provided as an extension to the C++ standard, which has meant that the details of that support varies between compilers and platforms. However, with the new standard, all compilers will have to conform to the same memory model and provide the same facilities for multi-threading (though implementors are still free to provide additional extensions). What does this mean for you? It means you'll be able to port multi-threaded code between compilers and platforms with much reduced cost. This will also reduce the number of different APIs and syntaxes you’ll have to know when writing for multiple platforms. The core of the new thread library is the std::thread class, which manages a thread of execution, so let's start by looking at that. Launching Threads You start a new thread by constructing an instance of std::thread with a function. This function is then used as the entry point for the new thread, and once that function returns, the thread is finished:

void do_work(); std::thread t(do_work);
This is just like the thread-creation APIs we're all used tobut there's a crucial difference: This is C++, so we're not restricted to functions. Just like many of the algorithms in the Standard C++ Library, std::thread will accept an object of a type that implements the function call operator (operator()), as well as ordinary functions:

class do_work { public: void operator()(); };

Simpler Multithreading in C++0x

do_work dw; std::thread t(dw);
It's important to note that this actually copies the supplied object into the thread. If you really want to use the object you supplied (in which case, you'd better make sure that it doesn't get destroyed before the thread finishes), you can do so by wrapping it in std::ref:

do_work dw; std::thread t(std::ref(dw));
Most thread creation APIs allow you to pass a single parameter to your newly created thread, typically a long or a void*. std::thread allows arguments too, but you can pass any number, of (almost) any type. Yes, you read that right: any number of arguments. The constructor uses C++0x's new variadic template facility to allow a variable number of arguments like the old ... varargs syntax, but in a type-safe manner. You can now pass objects of any copyable type as arguments to the thread function:

void do_more_work(int i,std::string s,std::vector v); std::thread t(do_more_work,42,"hello",std::vector(23,3.141));
Just as with the function object itself, the arguments are copied into the thread before the function is invoked, so if you want to pass a reference you need to wrap the argument in std::ref:

void foo(std::string&); std::string s; std::thread t(foo,std::ref(s));
OK, that's enough about launching threads. What about waiting for the thread to finish? The C++ Standard calls that "joining" with the thread (after the POSIX terminology), and you do that with the join() member function:

void do_work(); std::thread t(do_work); t.join();
If you're not planning on joining with your thread, just destroy the thread object or call detach():

void do_work(); std::thread t(do_work); t.detach();
Now, it's very well launching all these threads, but if you're going to share data you'd better protect it. The new C++ Standard Library provides facilities for that, too.

Simpler Multithreading in C++0x

Protecting Data In the C++0x thread library, as with most thread APIs, the basic facility for protecting shared data is the mutex. In C++0x, there are four varieties of mutexes:
● ● ● ●

non-recursive (std::mutex) recursive (std::recursive_mutex) non-recursive that allows timeouts on the lock functions (std::timed_mutex) recursive mutex that allows timeouts on the lock functions (std::recursive_timed_mutex)

All of them provide exclusive ownership for one thread. If you try and lock a non-recursive mutex twice from the same thread without unlocking in between, you get undefined behavior. A recursive mutex simply increases the lock countyou must unlock the mutex the same number of times that you locked itin order for other threads to be allowed to lock the mutex. Though these mutex types all have member functions for locking and unlocking, in most scenarios the best way to do it is with the lock class templates std::unique_lock and std::lock_guard. These classes lock the mutex in the constructor and release it in the destructor. Thus, if you use them as local variables, your mutex is automatically unlocked when you exit the scope:

std::mutex m; my_class data; void foo() { std::lock_guard lk(m); process(data); } // mutex unlocked here std::lock_guard is deliberately basic and can only be used as shown. On the other hand, std::unique_lock allows for deferred locking, trying to lock, trying to lock with a timeout, and unlocking before the object is destroyed. If you've chosen to use std::timed_mutex because you want the timeout on the locks, you probably need to use std::unique_lock:

std::timed_mutex m; my_class data; void foo() { std::unique_lock lk(m,std::chrono::milliseconds(3)); // wait up to 3ms if(lk) // if we got the lock, access the data process(data); } // mutex unlocked here
These lock classes are templates, so they can be used with all the standard mutex types, plus any

Simpler Multithreading in C++0x

additional types that supply lock() and unlock() functions. Protecting Against Deadlock When Locking Multiple Mutexes Occasionally, an operation requires you to lock more than one mutex. Done wrong, this is a nasty source of deadlocks: Two threads can try and lock the same mutexes in the opposite order, with each end upholding one mutex and waiting for the other thread to finish with the other mutexes. The C++0x thread library allievates this problem, in those cases where you wish to acquire the locks together, by providing a generic std::lock function that can lock multiple mutexes at once. Rather than calling the lock() member function on each mutex in turn, you pass them to std::lock(), which locks them all without risking deadlock. You can even pass in currently unlocked instances of std::unique_lock:

struct X { std::mutex m; int a; std::string b; }; void foo(X& a,X& b) { std::unique_lock lock_a(a.m,std::defer_lock); std::unique_lock lock_b(b.m,std::defer_lock); std::lock(lock_a,lock_b); } // do something with the internals of a and b

In the above example, suppose you didn't use std::lock. This could possibly result in a deadlock if one thread did foo(x,y) and another did foo(y,x) for two X objects x and y. With std::lock, this is safe.

Protecting Data During Initialization If your data only needs protecting during its initialization, using a mutex is not the answer. Doing so only leads to unnecessary synchronization after initialization is complete. The C++0x standard provides several ways of dealing with this. First, suppose your constructor is declared with the new constexpr keyword and satisfies the requirements for constant initialization. In this case, an object of static storage duration, initialized with that constructor, is guaranteed to be initialized before any code is run as part of the static initialization phase. This is the option chosen for std::mutex, because it eliminates the possibility of race conditions with initialization of mutexes at a global scope:

class my_class { int i;

Simpler Multithreading in C++0x

public: constexpr my_class():i(0){} my_class(int i_):i(i_){} }; void do_stuff();

my_class x; // static initialization with constexpr constructor int foo(); my_class y(42+foo()); // dynamic initialization void f() { y.do_stuff(); // is y initialized? }
Your second option is to use a static variable at block scope. In C++0x, initialization of block scope static variables happens the first time the function is called. If a second thread should call the function before the initialization is complete, then that second thread has to wait:

void bar() { static my_class z(42+foo()); // initialization is thread-safe } z.do_stuff();

If neither options apply (perhaps because the object is dynamically allocated), then it's best to use std:: call_once and std::once_flag. As the name suggests, when std::call_once is used in conjunction with a specific instance of type std::once_flag, the specified function is called exactly once:

my_class* p=0; std::once_flag p_flag; void create_instance() { p=new my_class(42+foo()); } void baz() { std::call_once(p_flag,create_instance); p->do_stuff(); }

Simpler Multithreading in C++0x

Just as with the std::thread constructor, std::call_once can take function objects instead of functions, and can pass arguments to the function. Again, copying is the default, and you have to use std::ref if you want a reference.

Waiting for Events If you're sharing data between threads, you often need one thread to wait for another to perform some action, and you want to do this without consuming any CPU time. If a thread is simply waiting for its turn to access some shared data, then a mutex lock can be sufficient. However, generally doing so won't have the desired semantics. The simplest way to wait is to put the thread to sleep for a short period of time. Then check to see if the desired action has occurred when the thread wakes up. It's important to ensure that the mutex you use to protect the data indicating that the event has occurred is unlocked whilst the thread is sleeping:

std::mutex m; bool data_ready; void process_data(); void foo() { std::unique_lock lk(m); while(!data_ready) { lk.unlock(); std::this_thread::sleep_for(std::chrono::milliseconds(10)); lk.lock(); } process_data(); }
This method may be simplest, but it's less than ideal for two reasons. Firstly, on average, the thread will wait five ms (half of ten ms) after the data is ready before it will wake in order to check. This may cause a noticeable lag in some cases. Though this can be improved by reducing the wait time, it exacerbates the second problem: the thread has to wake up, acquire the mutex, and check the flag every ten mseven if nothing has happened. This consumes CPU time and increases contention on the mutex, and thus potentially slows down the thread performing the task for which it's waiting! If you find yourself writing code like that, don't: Use condition variables instead. Rather than sleeping for a fixed period, you can let the thread sleep until it has been notified by another thread. This ensures that the latency between being notified and the thread waking is as small as the OS will allow, and effectively reduces the CPU consumption of the waiting thread to zero for the entire time. You can rewrite foo to use a condition variable like this:

std::mutex m;

Simpler Multithreading in C++0x

std::condition_variable cond;

bool data_ready; void process_data(); void foo() { std::unique_lock lk(m); while(!data_ready) { cond.wait(lk); } process_data(); }
Note that the above code passes in the lock object lk as a parameter to wait(). The condition variable implementation then unlocks the mutex on entry to wait(), and locks it again on exit. This ensures that the protected data can be modified by other threads whilst this thread is waiting. The code that sets the data_ready flag then looks like this:

void set_data_ready() { std::lock_guard lk(m); data_ready=true; cond.notify_one(); }
You still need to check that the data is ready though, since condition variables can suffer from what are called spurious wakes: The call to wait() may return even though it wasn't notified by another thread. If you're worried about getting this wrong, you can pass that responsibility off to the standard library too, if you tell it what you're waiting for with a predicate. The new C++0x lambda facility makes this really easy:

void foo() { std::unique_lock lk(m); cond.wait(lk,[]{return data_ready;}); process_data(); }
What if you don't want to share your data? What if you want exactly the opposite: For each thread to have its own copy? This is the scenario addressed by the new thread_local storage duration keyword.

Simpler Multithreading in C++0x

Thread Local Data The thread_local keyword can be used with any object declaration at namespace scope at local scope, and specifies that such a variable is thread local. Each thread thus has its own copy of that variable, and that copy exists for the entire duration of that thread. It is essentially a per-thread static variable, so each thread's copy of a variable declared at local scope is initialized the first time that particular thread passes through the declaration, and they retain their values until that thread exits:

std::string foo(std::string const& s2) { thread_local std::string s="hello"; s+=s2; return s;

}

In this function, each thread's copy of s starts life with the contents "hello." Every time the function is called, the supplied string is appended to that thread's copy of s. As you can see from this example, this even works with class types that have constructors and destructors (such as std::string), which is an improvement over the pre-C++0x compiler extensions. Thread-local storage isn't the only change to the concurrency support in the core language: There's also a brand new multi-threading aware memory model, with support for atomic operations. The New Memory Model and Atomic Operations Sticking to using locks and condition variables to protect your data, you won't need to worry about the memory model. The memory model guarantees to protect your data from race conditionsif you use locks correctly. You'll get undefined behavior if you don't. If you're working at a really low-level and providing high-performance library facilities, then it's important to know the detailswhich are too complicated to go into here. For now, it's enough to know that C++0x has a set of atomic types corresponding to the built-in integer types and void pointersand a template std:: atomicwhich can be used to create an atomic version of a simple user-defined type. You can look up the relevant documentation for the details. That's All, Folks! And that’s your whistle-stop tour of the new C++0x threading facilities, which has barely scratched the surface. There's much more to the library, with features such as thread IDs and asynchronous future values. Anthony Williams is the Technical Director for Just Software Solutions Ltd., where he spends most of his time developing custom software for clients, mostly for Windows, and mostly C++. He is the maintainer of the Boost Thread library and is also a member of the BSI C++ Standards Panel. His latest book, 'C++ Concurrency in Action: Practical Multithreading' is currently available in the Early Access Edition from Manning's web site.
DevX is a division of Jupitermedia Corporation © Copyright 2007 Jupitermedia Corporation. All Rights Reserved. Legal Notices

C++0x: The Dawning of a New Standard

The State of the Language: An Interview with Bjarne Stroustrup

The State of the Language: An Interview with Bjarne Stroustrup

C++Ox: The Dawning of a New Standard
Originally from http://www.devx.com/SpecialReports/Article/38813

The State of the Language: An Interview with Bjarne Stroustrup
C++ founding father assesses the language on the eve of its new standard. by Danny Kalev

Bjarne Stroustrup, inventor of the C++ programming language, is a computer scientist and the College of Engineering Chair Professor of Computer Science at Texas A&M University. He has always been highly involved in the standardization of C++. Since 2004, Bjarne and the standards committee have been busy hammering out the details of a new standard, temporarily titled C++0x. Bjarne was gracious enough to take time out of his busy schedule to speak with DevX C++ Pro, Danny Kalev, about new C++0x features and the state of the C++ language.

The C++0x standard will be finalized during 2009. Can you outline its major features and its overall importance to the C++ community?

We hope to vote out a draft standard for public review in October 2008 so that we'll be able to hand in a final draft for international vote in 2009. Because of this heavy ISO process, it's touch and go whether C++0x will be C++09, but there is still hope and the major features are now known (barring disasters). We can classify the extensions like this Concurrency:
● ● ● ● ● ●

memory model supporting modern machine architectures Threading ABI atomic types mutexes and locks thread local storage asynchronous message exchange

Libraries:
● ● ● ● ● ● ● ●

regex: regular expressions unordered_map, etc. (hash tables) smart pointers array: fixed-sized array improvements to containers based on new C++0x features tuples date and time (maybe) various library components to held library builders

Language:
● ●

rvalue references (move semantics) static_assert: static assertions

The State of the Language: An Interview with Bjarne Stroustrup
● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●

variadic templates strongly typed enumerations with scoped enumerators constexpr: generalized constant expressions control of alignment delegating and inheriting constructors auto: deducing a type from an initializer decltype: a way of using the type of an expression in a declaration control of defaults nullptr: a name for the null pointer a range-based for loop lambda functions raw string literals UTF8 literals concepts (a type system for template arguments) initializer lists and uniform initializations syntax and semantics in-class member initializers

Lists are, by themselves, not very interesting, but you can read up on a description of my general philosophy for language evolution and some of the individual decisions in my HOPL-iii paper "Evolving a language in and for the real world: C++ 1991-2006." You can also find more information than you could possibly want on the committee's web site. Basically, the "concurrency" features will standardize the basic layers needed to do systems programming in a multi-core world. Obviously, facilities for doing that already exist in C++ implementations, but they are not standardized. I'd have liked to see library support for some high-level concurrency models, but the committee didn't have the time or consensus for that. The library facilities provide a set of new library components and some improvements to the existing ones. I would have liked to see many more, but the committee is a volunteer effort and we just didn't have the resources for a massive extension of what was offered. Fortunately, there are many libraries available "out there," possibly already on your machine. For example, many of the C++0x libraries (e.g., regex and unordered_map) are now shipped by major vendors and boost.org offers many components (for instance, file system and networking) that we'll probably soon see in the standard. There is also much talk of a technical report on the libraries we most wanted but had to postpone.

"I'd have liked to see library support for some high-level concurrency models, but the committee didn't have the time or consensus for that."

The language extensions are a varied lot. Fortunately most are small and fit together with each other and with existing facilities to make a better integrated language. Consider a few examples:

// using C++0x features: vector v = {"Gorm", "Harald", "Sven", "Harald", "Knud" }; for (auto p = v.begin(); p!=v.end(); ++p) cout

Similar Documents

Premium Essay

My Interest In Mathematics

...challenging problems in science and engineering or related fields by using numerical computation have reached to a new level. Computation is today considered as a very important tool needed for the advancement of scientific knowledge and engineering practice along with theory and experiment. In the modern world all sorts of calculations are done by sophisticated computer systems. Every company and research farms from small-scale to large-scale are getting more and more reliant on mathematical principles these days. Numerical simulation has enabled the study of complex systems and natural phenomena that would be too expensive or sometimes impossible, to study directly by experimentation. As a matter of fact, engineers and scientists now require solid knowledge of computer science and applied mathematics in order to get optimized output from a system. To make things easier in this matter, Scientific Computing is a discipline that conglomerates Mathematics, Computer Science and Engineering in a single degree program and utilizes mathematical models in computer simulations to solve complex problems for not only in science laboratories but also in business and engineering firms. I have always been fascinated by the application of mathematics and computer science in the real world problems. That is why...

Words: 842 - Pages: 4

Free Essay

Biometric Uid Authentication Using Visual Cryptography

...Information Forensics and Security, vol. 1, no. 2, Jun. 2006. [2] C. Blundo, A. De Santis, and D.R. Stinson. On the contrast in visual cryptography schemes. J. Cryptogr., 12:261-289, 1999. [3] J. B. Feng, H. C. Wu, C. S. Tsai, Y. F. Chang, and Y. P. Chu. Visual secret sharing for multiple secrets. Pattern Recognition, 41:3572-3581, 2008. [4] A. Ross and A. A. Othman, “Visual Cryptography for Biometric privacy”, IEEE Transaction on Information Forensics and Security, vol. 6, no. 1, Mar.2011. [5] M. Naor and B A. Shamir. Visual cryptography. in: A. De San tis (Ed.), Advances in Cryptology: Eurpocrypt'94, Lecture Notes in Computer Science, 950: 1-12, 1995. [6] C.C. Wu and L.H. Chen. A study on visual cryptography, Master Thesis. PhD thesis, Institute of Computer and Information Science, National Chiao Tung University, Taiwan, R.O.C., 1998. [7] M. Naor and A. Shamir “Visual cryptography:Improving the contrast via the cover base” IACR Eprint archive, 1996. [8] C. Blundo and A. De Santis and D.R. Stinson, “On the contrast in visual cryptography schemes”, Jurnal pf cryptography, vol. 12, pp. 261-289, 1996. [9] G. Ateniese and C. Blundo and A. De Santis and D.R. Stinson,“Extended Schemes for Visual Cryptography”, Theoretical Computer Science, 1996. [10] Z. Zhouand and G. R. Arce and G. Di Crescenzo, “Halftone visual cryptography” IEEE Trans. Image Process, vol. 15, no. 8, pp. 2441-2453, Aug. 2006. [11] C. Blundo and A. De Santis and M. Naor, “Visual cryptography for grey...

Words: 715 - Pages: 3

Premium Essay

Computer Science Purpose Statement

...My purpose of applying to Masters in Computer Science at Arizona State University is to gain skills and knowledge to accelerate the innovative research and development happening in the field of computer science. Ever since I was a child, I have always dreamed of advancements in science and technology that would make humans a truly multi-planetary species in the near future. I have been keenly following the novel developments in the field of Machine Learning and Artificial Intelligence and strongly believe that AI will be at the helm of future outer space or deep sea explorations. This passion and curiosity is what led me onto the path I am on now and the research conducted at ASU in X, Y labs has inspired me only further. The motivation to accomplish my dream provided me with the zeal to excel right from my schooldays. I consistently topped my class and particularly enjoyed learning physics, computer science and mathematics. Being more inclined to learn by application, I decided to pursue engineering rather than pure science after high school, and Engineering Physics and Computer Science were my top preferences. I had my eyes set on the...

Words: 1205 - Pages: 5

Premium Essay

Dennis M. Ritchie's Accomplishments

...He was a man who turned down the offer of making atomic bombs for the government, who created a computer language so efficient that it’s still in use today, and a man who received over half a dozen awards for his accomplishments. Without him, it would be very likely that programs like Apple’s iOS wouldn’t exist. Dennis M. Ritchie’s contributions changed the field of Computer Science. He helped develop Unix and wrote books on computer programming, but his most significant accomplishment was creating C, a computer language. In fact, one of Ritchie’s colleagues once said that Ritchie’s code was “elegant and spare”. On September 9, 1941 in Bronxville, New York, Dennis M. Ritchie was born to Alistair Ritchie and Jean McGee Ritchie. His father,...

Words: 384 - Pages: 2

Free Essay

Cloud Load Balancing Techniques : a Step Towards Green Computing

...IJCSI International Journal of Computer Science Issues, Vol. 9, Issue 1, No 1, January 2012 ISSN (Online): 1694-0814 www.IJCSI.org 238 Cloud Load Balancing Techniques : A Step Towards Green Computing Nidhi Jain Kansal1, Inderveer Chana2 1 Computer Science and Engineering Department, Thapar University Patiala-147004, Punjab, India 2 Computer Science and Engineering Department, Thapar University Patiala-147004, Punjab, India Abstract Cloud computing is emerging as a new paradigm of large-scale distributed computing. It is a framework for enabling convenient, on-demand network access to a shared pool of computing resources. Load balancing is one of the main challenges in cloud computing which is required to distribute the dynamic workload across multiple nodes to ensure that no single node is overwhelmed. It helps in optimal utilization of resources and hence in enhancing the performance of the system. The goal of load balancing is to minimize the resource consumption which will further reduce energy consumption and carbon emission rate that is the dire need of cloud computing. This determines the need of new metrics, energy consumption and carbon emission for energy-efficient load balancing in cloud computing. This paper discusses the existing load balancing techniques in cloud computing and further compares them based on various parameters like performance, scalability, associated overhead etc. that are considered in different techniques. It further discusses...

Words: 5791 - Pages: 24

Free Essay

Mumbai University

...Link : http://www.indiastudycenter.com/other/syllabus/maharastra/mumuniv/degree/bsccs/default.asp Syllabus of Bachelor of Science (B.Sc) - Computer Science of University of Mumbai | Ist Year IInd Year IIIrd Year | Syllabus of Ist Year - Bachelor of Science (BSc) of University of Mumbai | Ist Year | Paper I Section 1 - Computer Organisation Section 2 - Ms-Windows and Ms-office Paper II Section 1 - Programming techniques and Algorithms through C Section 2 - Networking and Internet fundamentals | | Syllabus of IInd Year - Bachelor of Science (BSc) of University of Mumbai | Paper I Section 1 - Data structures with advanced C Section 2 - Event drive programming using Visual Basic Paper II Section 1 - Numerical Analysis with "C" Section 2 - Introduction to Java Paper III Section 1 - Introduction to file and Database Management Systems Section 2 - Principles of Rational Database Management System | Syllabus of IIIrd Year - Bachelor of Science (BSc) of University of Mumbai | Paper I Section 1 - System Software Section 2 - Data Communication and Networking Paper II Section 1 - Advanced Java 1 Section 2 - Advanced Java 2 Paper III Section 1 - Operating Systems Section 2 - The Linux OS Paper IV Section 1 - Structured System Analysis and Design Section 2 - Object Oriented Analysis and Design and Software Engineering Concepts Applied Components: Web Design and Applications Paper I - Principles of Web Design Paper II...

Words: 502 - Pages: 3

Free Essay

Computative Reasoning

...Scott Clark Graduate Student, DOE Computational Science Graduate Fellow 657 Rhodes Hall, Ithaca, NY, 14853 September 19, 2011 sc932@cornell.edu cam.cornell.edu/∼sc932 Education Cornell University Ph.D. Applied Math (current), M.S. Computer Science Ithaca, NY 2008 - 2012(projected) • – Department of Energy Computational Science Graduate Fellow (Full Scholarship, 4 years) – Emphasis on machine learning/data mining and algorithm design/software development related to bioinformatics and optimization • Oregon State University B.Sc. Mathematics, B.Sc. Computational Physics, B.Sc. Physics Corvallis, OR 2004 - 2008 – Graduated Magna Cum Laude with minors in Actuarial Sciences and Mathematical Sciences – Strong emphasis on scientific computing, numerical analysis and software development Skills • Development: C/C++, Python, CUDA, JavaScript, Ruby (Rails), Java, FORTRAN, MATLAB • Numerical Analysis: Optimization, Linear Algebra, ODEs, PDEs, Monte Carlo, Computational Physics, Complex Systems, Iterative Methods, Tomology • Computer Science: Machine Learning, Data Mining, Parallel Programming, Data Structures, Artificial Intelligence, Operating Systems • Discovering and implementing new ideas. Give me an API and a problem and I will figure it out. • Diverse background in Math, Computer Science, Physics and Biology allows me to communicate to a wide scientific and general audience and begin contributing to any group immediately. • I have worked in many places in a myriad of...

Words: 673 - Pages: 3

Free Essay

Personal Information

...Y A R E D ABERA, BSc. (Computer Science and IT) Assistant Lecturer, Computer Science & Information Technology Department Mizan-Tepi University – Ethiopia Contact Number: +251-920-643778 Email ID: yared2001@live.com,yared3778@gmail.com Career Profile:  Presently working as Assistant Lecturer in MIZAN TEPI UNIVERSITY, Ethiopia From oct,18,2010… to till date Key strengths include:      Curriculum & Development Backward Design Unit Planning Student Evaluation & Assessment Progress Monitoring Honors & College Readiness      Practical based instruction Content oriented Classroom Management Program Development College-to-career Connection EDUCATION & CERTIFICATION:  B.Sc., (Computer Science and IT) with 3.25 GPA at Wollega University, Ethiopia. TECHNICAL PROFILE: Programming Languages Database Technologies GUI Tools Web Technologies Operating System Packages Multimedia Application Professional Experience:  Presently working as Assistant Lecturer in Mizan-Tepi University, Ethiopia for B.Sc(CS & IT) and I have delivered Courses Introduction to Computer Science, Fundamentals of Programming I and II, Professional Ethics In computing, Fundamentals of Database Systems, Data Structures and Algorithms, Computer Organization and Architecture, Data Communication and Computer Networking, Object Oriented Programming, Operating Systems, Internet Programming I ,Advanced Database System, Internet Programming II, Unix System Administration, System Analysis and Design, Event...

Words: 506 - Pages: 3

Premium Essay

A Career In Computer Science

...From childhood computers caught my eyes. There was something about them that always attracted my interest. Starting from paint, games , and then finally LOGO, my first ever experience with a programming language. It changed my whole perception about what we can do with computers. Gradually, in my high school I moved on to languages like C, Visual Basic, and C++ . This raised my interest towards computes more and it made me opt for Computer Science as my field in undergraduate course , in Maharaja Surajmal Institute Of Technology. In 2nd year I excelled in courses like software engineering and, java and web development, computer networks, computer architecture, database management system. These subjects fascinated me to so extent that I have...

Words: 886 - Pages: 4

Free Essay

Career as Computer Scientist

...Environmental Education Standout Annotated Bibliography Abrea, Alma. “Computer Scientist Job Description, Education Requirements and Career Outlook.” USnewsuniversitydirectory.com U.S News University Directory. 2012 web. 24 Mar. 2016 Alma considers a master degree is required or PhD in Computer Science is required for the job. She also says that it takes four years for a bachelor’s degree and five years for a PhD. She also argues that “most occupations in the field require a graduate degree.” Abrea writes for usnewsdirectory.com which is a university directory web site. Abrea doesn’t have a bias. This editorial contradicts come of my other sources, which claim that a college degree is needed for computer science. Hoffman, Micheal. “A Guide to Computer Science Careers.” Computerscienceonline.org Computer Science Online. 2016 web. 24 Mar. 2016 Hoffman is a graduate of the University of California at Santa Barbara and the Santa Barbara College of Law, Hoffman began his professional career as an attorney in Los Angeles. After a brief period in the Hollywood film production business, Huffman now works as a freelance writer while he pursues his dream of becoming a published fiction author and screenwriter. Hoffman considers that a software developers get paid more than a User Interface Design. He argues that “User Interface Design annually makes $61,000 per year according to payscale.com and a Software Developer makes slightly over $100,000 in May 2013.” Huffman bias is that...

Words: 3203 - Pages: 13

Premium Essay

Wireless

...Manish Kumar Singh +91 – 9086185435 3rd year B.Tech Student manish.mrmanish.singh@gmail.com Computer Science and Engineering 2011ecs34@smvdu.ac.in Shri Mata Vaishno Devi University, Katra, Jammu Academic Details Academic Details Year | Degree | Institute | Percentage/CGPA | 2011-present | B.Tech In computerScience and Engineering | Shri Mata Vaishno Devi University,Katra,Jammu | CGPA=7.02/10Last semester SGPA=7.65/10 | 2010 | Class-XIIUP BOARD | Queens inter college, Varanasi, Uttar Pradesh | 80% | 2008 | Class-XUP BOARD | Queens inter college, Varanasi, Uttar Pradesh | 64.9%94% in mathematics87% in science | Objective Objective To use my knowledge of computer science to brighten the future of my nation. Projects Projects * Implemented a mobile jammer inside an RC helicopter Mr. Ajay Kaul Inspired from problems faced by security officials at 26/11 Mumbai Attacks, i tried to develop a remotely controlled mobile jammer ,which I put inside an RC helicopter this project was also approved by NATIONAL INSTRUMENTS OF INDIA, under a program called NIYANTRA, 2013. * House hold light detector ...

Words: 512 - Pages: 3

Free Essay

People

...Emplo yment Opportunities ■ Networking ● People Connection Memberships Professional affiliations Community organizations Social organizations ● Informational Interviews ■ ■ ■ Companies College Career Center Career-Related Experiences ● ● ● Part-time or full-time jobs Internships Volunteer positions ■ ■ Newspapers and Professional Publications Employment Agencies ● ● Private Government ■ Electronic Connection Transparency 8-1 Name School Teachers Ms. Nguyen Mr. Paleswski Students Cheryl (employed) Internet Postings at school and church Newspapers Co. web sites Frank & Frank North Hospital Apex Co. (S. Bing is mgr.) Postings at work Ads Professional Organization Web job board members Dr. Neus, mentor S. Bing (mgr. Apex Co.) Advisory Committee Tami Scholes Loretta Chu Family Friends Uncle Ron Jamie Soto (stylist; knows a lot of people) Coworkers N etw orking List Carlos (dad owns business) Transparency 8-2 Frame w ork for an Effectiv e Résumé Plan the Résumé Determine the objective: Secure an interview. Visualize your audience: Customize résumé for each audience. Gather supporting information: List responsibilities that relate to the employer’s requirements. Organize information into groups of employmentrelated facts. Emphasize information depending on position. Draft the Résumé Maintain ethics. Choose the best style. Determine keywords to include. Complete the Résumé Format for paper and Internet résumés...

Words: 3215 - Pages: 13

Premium Essay

Resume

...|REMARKS | |1. |2011 |QCF Level 7 POSTGRADUATE Diploma in Business Management (PgDip) |ASSOCIATION OF BUSINESS EXECUTIVES | |2. |2003 |British Computer Society (Honours Degree) in Information Technology |BRITISH COMPUTER SOCIETY – Graduated on | | | |(Certificate PGM, Diploma PGM, Professional Graduate Diploma, |the 4th of October 2003 | | | |Professional Project) | | |3. |2001 |Advanced Diploma in Business Administration |ASSOCIATION OF BUSINESS EXECUTIVES | Further Studies: 1. MBA (TopUp) University of Sunderland (UK) - 2012 - Global Corporate Strategy - International Business Environment - Dissertation Education: | |YEAR |EXAMINATION LEVEL |BODY/INSTITUTION | |1. |2011 |QCF Level 7 Postgraduate Diploma in Business Management |ASSOCIATION OF BUSINESS EXECUTIVES | |2. |Apr 2003 |Professional Graduate Diploma (Hons. Degree), Information |BRITISH COMPUTER SOCIETY | | |...

Words: 2182 - Pages: 9

Free Essay

Java Programming

...Registerable Courses for B.Sc. Computer Science June 2014 100 Level Course Code 1st Semester GST 101 GST 107 CIT 101 CIT 143 MTH 133 MTH 121 PHY 111 PHY 113 PHY 191 Course Titles Unit(s) Status Use of English and Communication Skill I The Good Study Guide Computers in Society Introduction to Data Organisation and Management Trigonometry Linear Algebra I Elementary Mechanics Heat and Properties of Matter Introductory Practical Physics I * Students are expected to offer at least one elective course per semester. Also they can only register a maximum of 25 units per semester Total Credit Unit - Compulsory Total Credit Unit - Elective Total Credit Units 2 2 2 2 2 2 2 2 2 C C C C C C C C C 18 0 18 2 2 2 2 2 2 2 2 2 2 C C C C C C C C C C 2nd Semester GST 102 Use of English and Communication Skills II GST 105 History and Philosophy of Science CIT 102 Software Application Skills MTH 102 Introductory Statistics MTH 112 Differential Calculus MTH 122 Integral Calculus MTH 142 Vectors and Geometry PHY 124 Geometric and Wave Optics PHY 132 Electricity, Magnetism and Modern Physics PHY 192 Introductory Practical Physics II * Students are expected to offer at least one elective course per semester. Also they can only register a maximum of 25 units per semester Total Credit Unit - Compulsory Total Credit Unit - Elective Total Credit Units 20 0 20 200 Level Course Code 1st Semester GST 201 CIT 211 GST 203 CIT 213 CIT 215 CIT 237 MTH 211 MTH 213 MTH 241 MTH 281 Course Titles...

Words: 911 - Pages: 4

Premium Essay

Personal Statement

...aspects of technology. Therefore, this has led me through a successful opportunity in the discipline of computer science and information. While I was in school, I acquired substantial information regarding how computers can be programmed and also used with the growth in technology. Since this period, my desire and fascination in computers and programming grew rapidly. When I joined secondary school, I learned various programming languages including C++ and HTML. This enabled me to conduct a presentation concerning these languages during the career day in the school. My fellow students were extremely amazed based on my understanding of the languages. After this session, I was utterly motivated to select computer science as a personal career. I was satisfied from the decision because, I usually enjoy acquiring new skills and information. In most cases, I use the acquired skills to enable my adaptation in the fast-changing world. This has also enhanced my interest in the innovation sector. According to my personal thinking, computer science would give me an incentive to improve personally and gain information. When I joined the University in Saudi Arabia, I was familiar with most of the freshman courses in the discipline of computer science and information. The facile nature of computers has even made it possible for me to gain more information in the study of computer science and information. Moreover, the versatility...

Words: 787 - Pages: 4