uBit.radio¶
Overview¶
The central processor unit (CPU) on the micro:bit is a Nordic Semiconductor nRF51822. In addition to being a general purpose computer processor, this chip also contains a built-in 2.4GHz radio module. This radio can be configured in a number of ways, and is primarily designed to run the Bluetooth Low Energy (BLE) protocol. However, it can also be placed into a much simpler mode of operation based that allows simple, direct micro:bit to micro:bit communication.
The MicroBitRadio
component is made up of three classes - MicroBitRadio
, MicroBitRadioEvent
and MicroBitRadioDatagram
. Together,
these provide the ability to send general purpose data packets from one micro:bit to another, and to extend a message bus to span multiple micro:bits...
so if you raise an event on one micro:bit, you can receive it on another using the normal listen mechanism!
Note
It is not currently possible to run the MicroBitRadio
component and Bluetooth Low Energy (BLE) at the same time. If you want to use the MicroBitRadio
functionality, you need to disable the BLE stack on your micro:bit by compiling the runtime with #define MICROBIT_BLE_ENABLED 0
in your inc/MicroBitConfig.h
file.
Capabilities¶
This component provides a very easy to use, flexible, broadcast radio channel. Anything you send from one micro:bit, can be received by any other micro:bits nearby. It is designed to provide a powerful but simple introduction to the world of wireless communications, and can let you create a whole range of applications from building your own friend detectors to creating remote control cars.
A key principle of this component is privacy, which is built in from the ground up. So, when you send any data, there is nothing inherent in this protocol which can be used to identify you or your micro:bit. All devices look identical. Therefore, if you want to be able to identify yourself, you need to add this to your own data.
| Capability | Brief Description |
|---|---|
| Frequency | 1MHz narrowband, typically 2.407 GHz. Use configurable in the 2.400 GHz - 2.499 GHz band. |
| Channel Rate | 1Mbps. |
| Maximum Transfer Unit | Typically 32 bytes, but reconfigurable in code up to 1024 bytes. |
| Addressing | All devices share the same address to guarantee user privacy. |
| Encryption | None. User level encryption (or BLE) should be considered if secture channels are required. |
| Meshing | None. (yet!) |
| Error Detection | 16 bit hardware CRC. |
| Transmisson Power | Eight user configurable settings from 0 (-30dbm) to 7 (+4dbm). |
| Transmisson Range | Approx. 20m at 0dbm. |
Using MicroBitRadio¶
To write your radio enabled applications, you will likely want to use either the MicroBitRadioDatagram
class, or the MicroBitRadioEvent
class.
Both of these are created for you as part of the standard uBit object, so this is a choice, not a compromise! :-)
MicroBitRadioDatagram¶
This is the most flexible way to use the radio, and lets you easily send and receive up to 32 bytes of data at a time.
This data can be provided as array of bytes, a text string, or PacketBuffer
.
You can send a packet at any time using the uBit.radio.datagram.send
function.
Any other micro:bits in range will detect the transmitted packet, and make the packet available through the
uBit.radio.datagram.recv
function.
Any micro:bits receiving a datagram packet will also raise a MICROBIT_RADIO_EVT_DATAGRAM
event to indicate
that some data is ready to be read.
For example, imagine you were creating a simple remote control car with one micro:bit acting as a remote controller, and another connected to some servos on the car.
You might decide that simply sending a 1
means turn left, and a 2
means turn right, so you may write a program like this for the remote control:
#include "MicroBit.h"
MicroBit uBit;
int main()
{
uBit.init();
uBit.radio.enable();
while(1)
{
if (uBit.buttonA.isPressed())
uBit.radio.datagram.send("1");
else if (uBit.buttonB.isPressed())
uBit.radio.datagram.send("2");
uBit.sleep(100);
}
}
...and one like this for the remote control car:
#include "MicroBit.h"
MicroBit uBit;
void onData(MicroBitEvent e)
{
ManagedString s = uBit.radio.datagram.recv();
if (s == "1")
{
uBit.io.P0.setServoValue(0);
uBit.display.print("A");
}
if (s == "2")
{
uBit.io.P0.setServoValue(180);
uBit.display.print("B");
}
}
int main()
{
uBit.init();
uBit.messageBus.listen(MICROBIT_ID_RADIO, MICROBIT_RADIO_EVT_DATAGRAM, onData);
uBit.radio.enable();
while(1)
uBit.sleep(1000);
}
Using PacketBuffers¶
If you prefer to send a raw series of bytes rather than a text string (which is much more common in communication networks), you can use the PacketBuffer
type.
This gives total freedom over the data being shared. Simply create a PacketBuffer
of the size you need, and you can read or write data using standard C
array syntax.
For example, here is an similar program using a PacketBuffer
:
#include "MicroBit.h"
MicroBit uBit;
int main()
{
uBit.init();
uBit.radio.enable();
// Create a packet containing just a single byte.
PacketBuffer b(1);
while(1)
{
b[0] = 0;
if (uBit.buttonA.isPressed())
b[0] = 1;
else if (uBit.buttonB.isPressed())
b[0] = 2;
uBit.radio.datagram.send(b);
uBit.sleep(100);
}
}
...and one like this for the remote control car:
#include "MicroBit.h"
MicroBit uBit;
void onData(MicroBitEvent e)
{
PacketBuffer p = uBit.radio.datagram.recv();
if (p[0] == 1)
{
uBit.io.P0.setServoValue(0);
uBit.display.print("A");
}
if (p[0] == 2)
{
uBit.io.P0.setServoValue(180);
uBit.display.print("B");
}
}
int main()
{
uBit.init();
uBit.messageBus.listen(MICROBIT_ID_RADIO, MICROBIT_RADIO_EVT_DATAGRAM, onData);
uBit.radio.enable();
while(1)
uBit.sleep(1000);
}
MicroBitRadioEvent¶
It is also possible to transparently send and receive events over the MicroBitRadio
channel. This can provide very simple and easy to integrate
support for event driven applications. Once configured, an event raised on one micro:bit can be detected on another - in the just the same way as
a local event such as a button click.
To use this functionality, all that is needed is to register the event codes that you would like to be sent over the radio, then write event handlers
for the message bus as with all other events. See the documentation for the MicroBitMessageBus
for details of how to write
event handlers.
For example, if you wanted to share an event SOMETHING with another micro:bit whenever ButtonA is pressed, you might write code like this on the sending micro:bit:
#include "MicroBit.h"
MicroBit uBit;
#define MY_APP_ID 4000
#define SOMETHING 1
int main()
{
uBit.init();
uBit.radio.enable();
// Ensure the radio is listening out to forward our events
uBit.radio.event.listen(MY_APP_ID, MICROBIT_EVT_ANY);
// Just for varierty, this time we'll periodically check to see if a button if pressed.
// We can, of course, use an event handler for this too.
while(1)
{
if (uBit.buttonA.isPressed())
MicroBitEvent(MY_APP_ID, SOMETHING);
uBit.sleep(100);
}
}
...and on the micro:bits wanting to receive the event:
#include "MicroBit.h"
MicroBit uBit;
#define MY_APP_ID 4000
#define SOMETHING 1
void onSomething(MicroBitEvent e)
{
uBit.display.scrollAsync("Something!");
}
int main()
{
uBit.init();
uBit.messageBus.listen(MY_APP_ID, SOMETHING, onSomething);
uBit.radio.enable();
while(1)
uBit.sleep(1000);
}
Defining Groups¶
It is easy to imagine situations where you would like to have different groups of micro:bits communicating independently.
For example, consider a classroom where 8 groups of four children are working on different projects - it would not be very useful if packets sent by one group interfered with the other groups!
To address this, the MicroBitRadio
allows users to define a group to which their micro:bit belongs.
micro:bits can only ever be a member of one group at a time, and any packets sent will only be received by other micro:bits in the same group.
Groups are simply numbers, and a micro:bit's group can be set at anytime by the programmer through the setGroup
function. If a group is not specified, the default group of 0 will be used.
For example:
#include "MicroBit.h"
MicroBit uBit;
int main()
{
uBit.init();
uBit.radio.setGroup(10);
}
Message Bus ID¶
| Constant | Value |
|---|---|
| MICROBIT_ID_RADIO | 29 |
| MICROBIT_ID_RADIO_DATA_READY | 30 |
Message Bus Events¶
| Constant | Value |
|---|---|
| MICROBIT_RADIO_EVT_DATAGRAM | 1 |
API¶
Constructor¶
MicroBitRadio()¶
Description¶
Constructor.
Initialise the MicroBitRadio .
Note
This class is demand activated, as a result most resources are only committed if send/recv or event registrations calls are made.
MicroBitRadio( uint16_t id)¶
Description¶
Constructor.
Initialise the MicroBitRadio .
Parameters¶
uint16_tid
Note
This class is demand activated, as a result most resources are only committed if send/recv or event registrations calls are made.
setTransmitPower¶
int setTransmitPower( int power)¶
Description¶
Change the output power level of the transmitter to the given value.
Parameters¶
intpower - a value in the range 0..7, where 0 is the lowest power and 7 is the highest.
Returns¶
MICROBIT_OK on success, or MICROBIT_INVALID_PARAMETER if the value is out of range.
setFrequencyBand¶
int setFrequencyBand( int band)¶
Description¶
Change the transmission and reception band of the radio to the given channel
Parameters¶
intband - a frequency band in the range 0 - 100. Each step is 1MHz wide, based at 2400MHz.
Returns¶
MICROBIT_OK on success, or MICROBIT_INVALID_PARAMETER if the value is out of range, or MICROBIT_NOT_SUPPORTED if the BLE stack is running.
getRxBuf¶
FrameBuffer getRxBuf()¶
Description¶
Retrieve a pointer to the currently allocated receive buffer. This is the area of memory actively being used by the radio hardware to store incoming data.
Returns¶
a pointer to the current receive buffer.
queueRxBuf¶
int queueRxBuf()¶
Description¶
Attempt to queue a buffer received by the radio hardware, if sufficient space is available.
Returns¶
MICROBIT_OK on success, or MICROBIT_NO_RESOURCES if a replacement receiver buffer could not be allocated (either by policy or memory exhaustion).
setRSSI¶
int setRSSI( uint8_t rssi)¶
Description¶
Sets the RSSI for the most recent packet.
Parameters¶
uint8_trssi - the new rssi value.
Note
should only be called from RADIO_IRQHandler...
getRSSI¶
int getRSSI()¶
Description¶
Retrieves the current RSSI for the most recent packet.
Returns¶
the most recent RSSI value or MICROBIT_NOT_SUPPORTED if the BLE stack is running.
enable¶
int enable()¶
Description¶
Initialises the radio for use as a multipoint sender/receiver
Returns¶
MICROBIT_OK on success, MICROBIT_NOT_SUPPORTED if the BLE stack is running.
disable¶
int disable()¶
Description¶
Disables the radio for use as a multipoint sender/receiver.
Returns¶
MICROBIT_OK on success, MICROBIT_NOT_SUPPORTED if the BLE stack is running.
setGroup¶
int setGroup( uint8_t group)¶
Description¶
Sets the radio to listen to packets sent with the given group id.
Parameters¶
uint8_tgroup - The group to join. A micro:bit can only listen to one group ID at any time.
Returns¶
MICROBIT_OK on success, or MICROBIT_NOT_SUPPORTED if the BLE stack is running.
dataReady¶
int dataReady()¶
Description¶
Determines the number of packets ready to be processed.
Returns¶
The number of packets in the receive buffer.
recv¶
FrameBuffer recv()¶
Description¶
Retrieves the next packet from the receive buffer. If a data packet is available, then it will be returned immediately to the caller. This call will also dequeue the buffer.
Returns¶
The buffer containing the the packet. If no data is available, NULL is returned.
Note
Once recv() has been called, it is the callers resposibility to delete the buffer when appropriate.
send¶
int send( FrameBuffer * buffer)¶
Description¶
Transmits the given buffer onto the broadcast radio. The call will wait until the transmission of the packet has completed before returning.
Parameters¶
FrameBuffer *buffer
Returns¶
MICROBIT_OK on success, or MICROBIT_NOT_SUPPORTED if the BLE stack is running.


vapour content
Path: CARNOT/materials
Purpose
The block calculates the vapour content of the a
specified fluid property.
Description
The block calculates the vapour content of the fluid by evaluating the
specified fluid property_ID according to the inputs
The blocks performs the calculation
vapourcontent = (propvalue - (prop)')/((prop)" - (prop)')
The ' state is the boiling fluid, the " state is the saturated steam. If the fluid is in the two phase area (pressure == vapourpressure) the fluid value is in the interval [0..1]. In the case of pure fluid (pressure vapourpressure), the vapourcontent is 0, in the case of pure steam (pressure < vapourpressure), the vapourcontent is 1. The case determination for the vapourpressure is set to a interval of [0.98*vapourpressure .. 1.02*vapourpressure] because otherwise the vapourpressure has to meet the value of the vapourpressure function exactly, which is also not exact.
Parameters and Dialog Box
Characteristics
Direct Feedthrough Yes
Sample
time
Inherited
from driving block
Vectorized
No


--- layout: page-layout-1 title: (ASK) Quiz Funnel - Checkout nav_exclude: true ---
IMPORTANT: This is a ONE-TIME opportunity that EXPIRES when that countdown hits ZERO (Really). Complete your order NOW :-)
Your information and personal data are protected by the most advanced technology safeguards available. Our checkout process is fully encrypted to ensure that your personal and financial information is kept secure.
Payment secured by 256-bit encryption
"Ryan is a great business mentor and he’ll save you a tremendous amount of time and money."
Brendon Burchard, #1 New York Times Bestselling Author
"Whether you're starting a brand new business or expanding your existing business Ryan Levesque's training is an absolute must for every digital marketer."
Ryan Deiss CEO Digital Marketer
"If I were starting out again, I’d be using Ryan’s strategy to help me figure out and test ideas. His approach is adopted to today’s amazing digital-based tools."
Michael Masterson Best-Selling Author of Ready, Fire, Aim.
"Millions of failed entrepreneurs would probably be successful ones today had they had Ryan as their guide."
Jay Abraham America's #1 Marketing Expert
$1999.00 Ryan Levesque’s QUIZ Funnel Masterclass plus $99/month Access to Bucket.io 2.0
Subtotal $1999.00
Due Today $1999.00
All we ask is that you complete the course work from Module 1, Lesson 1, to show us that you at least gave it a try. If after completing this lesson you decide that the program isn’t for you, simply let us know and you’ll receive a swift and full refund. It’s really as simple as that!
Phone: 1-844-542-5275
Email: contact [at] askmethod [dot] com
Chat: Click below to ask your questions


Re-reading my previous post on data-centric security Hoff made the correct comment that I'd gone to the extreme end and it didn't quite flow from his post.
Fair point, I jumped a couple of hurdles a bit too quickly and it probably didn't make where I'm coming from clear, so I'll try and cover things a bit better now.
ok first basic point, I'm not a fan of *some* of the Jericho forums ideas (I like most of the others just fine, in principle anyway). Specifically the DRM/acces to data bit. In principle it sounds great, but I don't think that it's practible to implement in most organisations with their masses of un-organised data an ever increasing requirements for easier connectivity and data flow.
Now Rob makes the point very forcefully that models like Bell LaPudala have described the kind of Mandatory Access Control world that DRM implements for quite some time. Yep they have, but outside of miltiary or police environments I've never seen these implemented. My feeling is that the reason for this is that in these systems users need to be actively involved in data security, they need to classify information as it's created and they need to understand the requirements on them to maintain the classification of data.
I don't think that most corporates will buy into systems that work in that way. I think that the overhead of training and maintaining systems that implement MAC is beyond what most companies want.
So .. am I anti-security? Nope I'm extremely pro-security. My feeling is however that the best way to implement security is in ways which it's invisable to users. Every time you make ordinary business people think about security (eg, usernames/passwords) they try their darndest to bypass those requirements.
Personally I'm a great fan of network segregation and defence in depth at the network layer. I think that devices like the ones crossbeam produce are very useful in coming up with risk profiles, on a network by network basis rather than a data basis and managing traffic in that way. The reason for this is that then the segregation and protections can be applied without the intervention of end-users and without them (hopefully) having to know about what security is in place.
So to use the phrase that I've seen in other blogs on this subject, I think that the "zones of trust" are a great idea, but the zone's shouldn't be based on the data that flows over them, but the user/machine that are used. It's the idea of tagging all that data with the right tags and controlling it's flow that bugs me.
So that's where my points in the previous post came from, and I still reckon their correct. Data tagging and parsing relies on the existance of standards and their uptake in the first instance and then users *actually using them* and personally I think that's not going to happen in general companies and therefore is not the best place to be focusing security effort...


The Boost C++ Libraries
This book is licensed under a Creative Commons License.
Threads are discrete processing sequences that allow execution of different functions within a given application at the same time. This becomes important if a function, known to take a long time for a specific calculation, should not block a different function while executing. Threads actually allow the simultaneous execution of two functions without having one waiting for the other.
Once an application is launched, it contains only one thread by default. This thread executes the main()
function. Functions called from within main()
are executed sequentially in the context of this thread. Such a program is called a single threaded application.
In contrast, programs that create new threads are called multithreaded applications. Not only can they execute multiple functions at the same time, they also become more and more important these days since computers now ship with CPUs containing more than one core by default. Since multiple cores allow the execution of different functions simultaneously, they put a burden on the developer to use the available processing capacity accordingly. While threads have always been used whenever different functions should execute concurrently, developers now are more and more forced to carefully structure their applications to support this concurrency. Knowledge of multithreaded programming thus becomes more and more important in the age of multi-core systems.
This chapter introduces the Boost C++ Library Boost.Thread that allows the development of platform independent multithreaded applications.
The most important class in this library is boost::thread
, defined in boost/thread.hpp
, which is used to create a new thread. The following example shows how to apply it.
#include <boost/thread.hpp> #include <iostream> void wait(int seconds) { boost::this_thread::sleep(boost::posix_time::seconds(seconds)); } void thread() { for (int i = 0; i < 5; ++i) { wait(1); std::cout << i << std::endl; } } int main() { boost::thread t(thread); t.join(); }
The name of the function that should execute within the thread is passed to the constructor of boost::thread
. Once the variable t in the above example is created, the thread()
function starts executing in its own thread immediately. At this point, thread()
executes concurrently with the main()
function.
To keep the application from terminating, the join()
method is called on the newly created thread. join()
is a blocking call: It blocks the current thread until the thread, for which join()
was called, has terminated. This causes main()
to wait until thread()
has terminated.
As seen in the above example, a particular thread can be accessed via a variable such as t in order to e.g. wait for its termination using the join()
method. However, the thread will continue to execute even if t loses its scope and is destroyed. A thread always binds to a variable of type boost::thread
in the beginning, but once created, depends no longer on it. There even exists a method called detach()
that allows to decouple a variable of type boost::thread
from its corresponding thread. Certainly, methods such as join()
cannot be called afterwards since the variable does not represent a valid thread any longer.
Anything that can be done inside a function can also be done inside a thread. Ultimately, a thread is no different than a function - except that it is executed concurrently. In the example above, five numbers are written to the standard output stream using a loop. To slow down the output, every iteration of the loop calls the wait()
function to stall execution for one second. wait()
employs a function named sleep()
that also originates from Boost.Thread and resides in the boost::this_thread
namespace.
sleep()
either expects a period of time or a specific point in time indicating how long or until when the current thread should be stalled. By passing an object of type boost::posix_time::seconds
, a period of time is specified in this example. boost::posix_time::seconds
comes from the Boost.DateTime library that is used by Boost.Thread to manage and process time data.
While the previous example shows how to wait for a different thread, the following example rather shows how a thread can be interrupted by the means of so-called interruption points.
#include <boost/thread.hpp> #include <iostream> void wait(int seconds) { boost::this_thread::sleep(boost::posix_time::seconds(seconds)); } void thread() { try { for (int i = 0; i < 5; ++i) { wait(1); std::cout << i << std::endl; } } catch (boost::thread_interrupted&) { } } int main() { boost::thread t(thread); wait(3); t.interrupt(); t.join(); }
Calling interrupt()
on a thread object interrupts the corresponding thread. In this context, interrupted means that an exception of type boost::thread_interrupted
is thrown inside the thread. However, this only happens once the thread reaches an interruption point.
Simply calling interrupt()
does not cause anything if the given thread does not contain any interruption points. Whenever a thread reaches an interruption point it will check whether the interrupt()
method has been called. Only if it has, a boost::thread_interrupted
exception is thrown accordingly.
Boost.Thread defines a series of interruption points such as the sleep()
function. Since sleep()
is called five times in the example, the thread checks five times whether or not it was interrupted. Between the calls to sleep()
, the thread can not be interrupted though.
Once the program is executed, it will only print three numbers to the standard output stream. This is caused by calling the interrupt()
method after three seconds inside main()
. Thus, the corresponding thread is interrupted and throws a boost::thread_interrupted
exception accordingly. While the exception is correctly caught inside the thread, the catch
handler is empty though. Since the thread()
function returns after the handler, the thread is terminated as well. This in turn will also terminate the entire application since main()
simply waited for the thread to terminate using the join()
method.
Boost.Thread defines about ten interruption points including the mentioned sleep()
function. Thanks to these interruption points, threads can easily be interrupted in a timely manner. However, they may not always be the best choice since an interruption point must be reached first in order to check for the boost::thread_interrupted
exception.
To provide a rough overview over the different functions provided by Boost.Thread, the following example introduces two more.
#include <boost/thread.hpp> #include <iostream> int main() { std::cout << boost::this_thread::get_id() << std::endl; std::cout << boost::thread::hardware_concurrency() << std::endl; }
Using the namespace boost::this_thread
, independent functions are provided that apply to the current thread such as the sleep()
function shown before. Another one is get_id()
: It will return a number identifying the current thread. It is also provided as a method for boost::thread
.
The static hardware_concurrency()
method, provided by the boost::thread
class, returns the number of threads that could physically be executed at the same time based on the underlying number of CPUs or CPU cores. Calling this function on a commonly used dual-core machine, a value of 2 is returned. This allows for a simple method to identify the theoretical maximum number of threads that should be used simultaneously by a given multithreaded application.
While the usage of multiple threads can increase the performance of an application it usually also increases its complexity. If several functions execute at the same time using threads, access to shared resources must be synchronized accordingly. This involves quite some work once the application reaches a certain size. This paragraph introduces the classes provided by Boost.Thread for synchronizing threads.
#include <boost/thread.hpp> #include <iostream> void wait(int seconds) { boost::this_thread::sleep(boost::posix_time::seconds(seconds)); } boost::mutex mutex; void thread() { for (int i = 0; i < 5; ++i) { wait(1); mutex.lock(); std::cout << "Thread " << boost::this_thread::get_id() << ": " << i << std::endl; mutex.unlock(); } } int main() { boost::thread t1(thread); boost::thread t2(thread); t1.join(); t2.join(); }
Multithreaded programs use so-called mutex objects for synchronization. Boost.Thread provides different mutex classes, boost::mutex
being the most simple one. The basic principle of a mutex is to prevent other threads from taking ownership while a particular thread owns it. Once released, a different thread can take ownership. This causes threads to wait until a different thread has finished processing some operations and thus releases its ownership of the mutex object accordingly.
The above example uses a global mutex object of type boost::mutex
named mutex. The thread()
function takes ownership of this object right before it writes to the standard output stream inside the for
loop using the lock()
method. Once a message has been written, the ownership is released using the unlock()
method.
main()
creates two threads, both executing the thread()
function. Using the for
loop, every thread counts to five, writing a message to the standard output stream with each iteration. Unfortunately, the standard output stream is a global object which is shared among all threads. The standard does not provide any guarantee that std::cout can be safely accessed from multiple threads. Thus, access to the standard output stream must be synchronized: At any given time, only one thread is allowed to access std::cout.
Since both threads try to acquire the mutex before writing to the standard output stream, it is guaranteed that only one thread at a time actually accesses std::cout. Disregarding which thread successfully calls the lock()
method, all other threads need to wait until unlock()
has been called.
Acquiring and releasing mutexes is a typical scheme and is supported by Boost.Thread through different data types. For example, instead of calling lock()
and unlock()
directly, the boost::lock_guard
class can be used.
#include <boost/thread.hpp> #include <iostream> void wait(int seconds) { boost::this_thread::sleep(boost::posix_time::seconds(seconds)); } boost::mutex mutex; void thread() { for (int i = 0; i < 5; ++i) { wait(1); boost::lock_guard<boost::mutex> lock(mutex); std::cout << "Thread " << boost::this_thread::get_id() << ": " << i << std::endl; } } int main() { boost::thread t1(thread); boost::thread t2(thread); t1.join(); t2.join(); }
boost::lock_guard
automatically calls lock()
and unlock()
inside its constructor and destructor, respectively. Access to the shared resource is as synchronized as it was when calling both methods explicitly. The boost::lock_guard
class is yet another example of the RAII idiom presented in Chapter 2, Smart Pointers.
Besides boost::mutex
and boost::lock_guard
, Boost.Thread provides additional classes to support variations of synchronization. One of the essential ones is boost::unique_lock
which, compared to boost::lock_guard
, provides a number of helpful methods.
#include <boost/thread.hpp> #include <iostream> void wait(int seconds) { boost::this_thread::sleep(boost::posix_time::seconds(seconds)); } boost::timed_mutex mutex; void thread() { for (int i = 0; i < 5; ++i) { wait(1); boost::unique_lock<boost::timed_mutex> lock(mutex, boost::try_to_lock); if (!lock.owns_lock()) lock.timed_lock(boost::get_system_time() + boost::posix_time::seconds(1)); std::cout << "Thread " << boost::this_thread::get_id() << ": " << i << std::endl; boost::timed_mutex *m = lock.release(); m->unlock(); } } int main() { boost::thread t1(thread); boost::thread t2(thread); t1.join(); t2.join(); }
The above example uses various methods to illustrate some of the features provided by boost::unique_lock
. Certainly, the usage of these features does not necessarily make sense for the given scenario; the usage of boost::lock_guard
in the previous example was already adequate. This example is rather meant to demonstrate the possibilities offered by boost::unique_lock
.
boost::unique_lock
offers different ways of acquiring a mutex by providing multiple constructors. The one expecting only a mutex object simply calls the lock()
method and waits until the mutex has been acquired. It thus acts exactly the same as the one of boost::lock_guard
.
If a value of type boost::try_to_lock
is passed as the second parameter, the corresponding constructor calls try_lock()
instead. This method returns a value of type bool
: true
if the mutex could be acquired, false
if not. Opposed to the lock()
method, try_lock()
returns immediately and does not block until the mutex has been acquired.
The above program passes boost::try_to_lock as the second parameter to the constructor of boost::unique_lock
. Whether or not the mutex has been acquired can be checked via the owns_lock()
method afterwards. In case it has not - owns_lock()
returns false
- another function provided by boost::unique_lock
is used: timed_lock()
waits for a certain time to acquire the mutex. The given program waits for up to one second which should be more than enough time to acquire the mutex.
The example actually shows the three fundamental ways of acquiring a mutex: lock()
waits until the mutex has been acquired. try_lock()
does not wait but acquires the mutex if it is available at the time of the call and returns false
otherwise. Finally, timed_lock()
tries to acquire the mutex within a given period of time. As with try_lock()
, success or failure is indicated by the return value of type bool
.
While both lock()
and try_lock()
are provided by boost::mutex
, timed_lock()
is only supported by boost::timed_mutex
instead which is the reason for its usage in the above example program. Without using timed_lock()
, the mutex can be of type boost::mutex
as seen in the previous example.
Just like boost::lock_guard
, the destructor of boost::unique_lock
releases the mutex accordingly. In addition, the mutex can be manually released using the unlock()
method. It is also possible to remove the association between the boost::unique_lock
class and the mutex by calling release()
as done in the above example. In this case however, the mutex must be released using the unlock()
method explicitly as it is not done automatically by the destructor of boost::unique_lock
anymore.
boost::unique_lock
is a so-called exclusive lock meaning that only one thread at a time can acquire the mutex. Other threads are required to wait until the mutex has been released again. Besides exclusive locks there are also non-exclusive ones. Boost.Thread provides a class named boost::shared_lock
to support non-exclusive locks accordingly. This class must be used together with a mutex of type boost::shared_mutex
as shown in the following example.
#include <boost/thread.hpp> #include <iostream> #include <vector> #include <cstdlib> #include <ctime> void wait(int seconds) { boost::this_thread::sleep(boost::posix_time::seconds(seconds)); } boost::shared_mutex mutex; std::vector<int> random_numbers; void fill() { std::srand(static_cast<unsigned int>(std::time(0))); for (int i = 0; i < 3; ++i) { boost::unique_lock<boost::shared_mutex> lock(mutex); random_numbers.push_back(std::rand()); lock.unlock(); wait(1); } } void print() { for (int i = 0; i < 3; ++i) { wait(1); boost::shared_lock<boost::shared_mutex> lock(mutex); std::cout << random_numbers.back() << std::endl; } } int sum = 0; void count() { for (int i = 0; i < 3; ++i) { wait(1); boost::shared_lock<boost::shared_mutex> lock(mutex); sum += random_numbers.back(); } } int main() { boost::thread t1(fill); boost::thread t2(print); boost::thread t3(count); t1.join(); t2.join(); t3.join(); std::cout << "Summe: " << sum << std::endl; }
Non-exclusive locks of type boost::shared_lock
can be used if threads only need read-only access to a specific resource. A thread modifying the resource needs write access and thus requires an exclusive lock. The reason for that should be obvious: Threads with read-only access do not recognize other threads accessing the same resource at the same time. Non-exclusive locks can therefore share a mutex.
In the given example, both print()
and count()
access random_numbers read-only. While the print()
function writes the last number of random_numbers to the standard output stream, the count()
function adds it to the variable sum. Since neither function modifies random_numbers, both can access it at the same time using a non-exclusive lock of type boost::shared_lock
.
Inside the fill()
function, an exclusive lock of type boost::unique_lock
is required since it inserts new random numbers into random_numbers. The mutex is explicitly released using the unlock()
method before fill()
waits for one second. Opposed to the previous example, wait()
is called at the end of the for
loop to guarantee that at least one random number exists in the container before it is accessed by either print()
or count()
. Both of these functions call the wait()
function at the beginning of their for
loop accordingly.
Looking at the individual calls to the wait()
function from different locations, one potential issue becomes apparent: The order of the function calls is directly affected by the order in which the CPU actually executes the individual threads. Using so-called condition variables, the individual threads can be synchronized so that elements added to random_numbers are immediately processed by a different thread accordingly.
#include <boost/thread.hpp> #include <iostream> #include <vector> #include <cstdlib> #include <ctime> boost::mutex mutex; boost::condition_variable_any cond; std::vector<int> random_numbers; void fill() { std::srand(static_cast<unsigned int>(std::time(0))); for (int i = 0; i < 3; ++i) { boost::unique_lock<boost::mutex> lock(mutex); random_numbers.push_back(std::rand()); cond.notify_all(); cond.wait(mutex); } } void print() { std::size_t next_size = 1; for (int i = 0; i < 3; ++i) { boost::unique_lock<boost::mutex> lock(mutex); while (random_numbers.size() != next_size) cond.wait(mutex); std::cout << random_numbers.back() << std::endl; ++next_size; cond.notify_all(); } } int main() { boost::thread t1(fill); boost::thread t2(print); t1.join(); t2.join(); }
The program in this example removed the wait()
and count()
functions. Threads do no longer wait for one second with every loop iteration but rather execute as fast as possible. Additionally, no total is calculated; numbers are solely written to the standard output stream.
To ensure correct processing of the random numbers, the individual threads are synchronized by a conditional variable that allows to check for certain conditions between multiple threads.
As before, the fill()
function generates a random number with each iteration and places it in the random_numbers container. To block other threads from accessing the container at the same time, an exclusive lock is taken accordingly. Instead of waiting for one second, this example actually uses a conditional variable instead. Calling the notify_all()
method will wake up every thread that has been waiting for this notification by calling the wait()
method, respectively.
By looking at the for
loop of the print()
function, one can see that for the same conditional variable a method named wait()
is called. If the thread is woken up by a call to notify_all()
, it tries to acquire the mutex which will only succeed after it has been successfully released in the fill()
function.
The trick here is that calling wait()
also releases the corresponding mutex passed as parameter. After calling notify_all()
, the fill()
function releases the mutex by calling wait()
accordingly. It then blocks and waits for some other thread to call notify_all()
which happens in the print()
function once the random number has been written to the standard output stream.
Notice that the call to the wait()
method inside the print()
function actually happens within a separate while
loop. This is done to handle the scenario where a random number has already been placed in the container before the wait()
method is called for the first time in print()
. By comparing the number of stored elements in random_numbers with the expected number of elements, this scenario is successfully handled and the random number is written to the standard output stream.
Thread Local Storage (TLS) is a dedicated storage area that can only be accessed by one thread. TLS variables can be seen as global variables only visible to a particular thread instead of the whole program. The following example shows the benefits of these variables.
#include <boost/thread.hpp> #include <iostream> #include <cstdlib> #include <ctime> void init_number_generator() { static bool done = false; if (!done) { done = true; std::srand(static_cast<unsigned int>(std::time(0))); } } boost::mutex mutex; void random_number_generator() { init_number_generator(); int i = std::rand(); boost::lock_guard<boost::mutex> lock(mutex); std::cout << i << std::endl; } int main() { boost::thread t[3]; for (int i = 0; i < 3; ++i) t[i] = boost::thread(random_number_generator); for (int i = 0; i < 3; ++i) t[i].join(); }
The example creates three threads, each writing a random number to the standard output stream. The random_number_generator()
function utilizes the std::rand()
function, defined in the C++ standard, to create the random numbers. However, the generator used for std::rand()
must be properly initialized with the std::srand()
function. If not, the program will always print the same random number.
Initializing the random number generator takes place inside the init_number_generator()
function with the aid of the std::time()
function returning the current time. Since this value differs every time the application is executed, it is guaranteed that the generator is always initialized with a different value and thus provides new random numbers. Since the generator only needs to be initialized once, init_number_generator()
uses a static variable named done as the condition.
If the program is executed a couple of times, it becomes apparent that two of the three random numbers written are always the same. The program actually has a defect: The generator on which std::rand()
is based must be initialized for every thread using the function. Therefore, the implementation of init_number_generator()
is actually incorrect since it only calls std::srand()
once. Using TLS, this defect can be rectified.
#include <boost/thread.hpp> #include <iostream> #include <cstdlib> #include <ctime> void init_number_generator() { static boost::thread_specific_ptr<bool> tls; if (!tls.get()) tls.reset(new bool(false)); if (!*tls) { *tls = true; std::srand(static_cast<unsigned int>(std::time(0))); } } boost::mutex mutex; void random_number_generator() { init_number_generator(); int i = std::rand(); boost::lock_guard<boost::mutex> lock(mutex); std::cout << i << std::endl; } int main() { boost::thread t[3]; for (int i = 0; i < 3; ++i) t[i] = boost::thread(random_number_generator); for (int i = 0; i < 3; ++i) t[i].join(); }
The static variable done has been replaced with a TLS variable tls which is based on the template class boost::thread_specific_ptr
- instantiated with the data type bool
. In principle, tls works just like done: It acts as a condition indicating whether or not the random number generator has already been initialized. The crucial difference, however, is that the value stored by tls is only visible and available to the corresponding thread.
Once a variable of type boost::thread_specific_ptr
is created, it can be set accordingly. However, it now expects the address of a variable of type bool
instead of the variable itself. Using the reset()
method, the corresponding address can be stored in tls. In the given example, a variable of type bool
is dynamically allocated and its address, returned by new
, is stored in tls. To avoid setting tls every time the init_number_generator()
function is called, it first checks whether an address is already stored via the get()
method.
 Consequently, both the operator*()
and operator->()
operators are overloaded to simplify the usage. The example uses *tls
to check whether the condition is currently true
or false
. Depending on the current condition, the random number generator is either initialized or not.
As seen, boost::thread_specific_ptr
allows storing the address of an object for the current thread and only allows the current thread to retrieve the same address later on. While one thread already stored the address successfully, a different thread may have not.
If the program is now executed, it may come as a surprise that despite the TLS variable, the random numbers generated are still equal. This is due to the fact that all three threads are created at the same time and thus, the random number generators are initialized with the same time as well. If the program is executed a couple of times however, the random numbers will change indicating that the generators itself are initialized correctly.
You can buy solutions to all exercises in this book as a ZIP file.
Refactor the following program to calculate the total using two threads. Since many processors nowadays have two cores, the execution time should decrease by utilizing threads.
#include <boost/date_time/posix_time/posix_time.hpp> #include <boost/cstdint.hpp> #include <iostream> int main() { boost::posix_time::ptime start = boost::posix_time::microsec_clock::local_time(); boost::uint64_t sum = 0; for (int i = 0; i <<PHONE_NUMBER>; ++i) sum += i; boost::posix_time::ptime end = boost::posix_time::microsec_clock::local_time(); std::cout << end - start << std::endl; std::cout << sum << std::endl; }
Generalize the program from exercise 1 by utilizing as many threads as the processor can physically execute at the same time. For example, if the processor contains four cores, a total of four threads should be utilized.
Change the following program by executing the thread()
function in its own thread created in main()
. The program should calculate the total and write it to the standard output stream twice. The implementation of calculate()
, print()
and thread()
can be modified however, the signature of each function needs to stay the same. In other words, each function should still neither require any parameters nor return a value.
#include <iostream> int sum = 0; void calculate() { for (int i = 0; i < 1000; ++i) sum += i; } void print() { std::cout << sum << std::endl; } void thread() { calculate(); print(); } int main() { thread(); }
Copyright © 2008-2010 Boris Schäling


This text is bold
This text is bold
This text is bold
This text is strong
This text is italic
This text is emphasized
HTML
Smalll
Formatting
HTML
Marked
Formatting
Boy
Girl
Boy
girl
H
2
SO
4
H
+
+ Cl
-
= HCl


This inspection reports when a JBehave step declaration is not used in any of the story files. Note: May be CPU intensive for projects with a lot of story files.


It was built in november 1998, the first piece of the ISS was launched from Russia, the Zarya (control module).
About two weeks later, the space shuttle Endeavour meet Zarya in orbit. The space shuttle was carrying the U.S. Unity. The crew attached the Unity node to Zarya.
The Zarya Module, also known by the technical term Functional Cargo Block and the Russian acronym FGB, was the first component launched for the International Space Station.


An Object Request Broker in The Lua Language
OiL stands for ORB in Lua. It is a simple, efficient and flexible object request broker written in the Lua language. OiL shares some of the main characteristics of Lua, like simplicity, extensibility, small footprint and good performance. In particular, OiL's support for CORBA is far simpler than the mappings for languages as Java, C++ or Python. Besides that, the dynamic nature of a scripting language like Lua enables a more flexible implementation of the CORBA specification. Another important feature of OiL is portability because the Lua interpreter is entirely written in ANSI C, so it can be compiled in virtually any platform, from microcontrollers and cellular phones to PCs and mainframes. The project is at a young stage, therefore many aspects that must be addressed are still missing.
Currently, OiL supports only part of the CORBA specification. Although, it is intended to provide seamless support for many different ORB protocols. One of the main concerns of the OiL team is to maintain its implementation simple and lightweight, therefore some more advanced features of CORBA may not be supported or be replaced by features of the Lua language.


Toggle navigation
Partneran
explore
Explore
Sign In
Sign Up
account_circle
My Profile
add_circle
Share Idea
Sign Out


My Cheap Book Finder
Search Books:
Search
Book Image
Book Details:
Title:
Author:
Publisher:
Page Count:
Ebay Listings:


UnboxxEd is a hypothetical e-business that was created as an online marketing and business management exercise. As an in-house web development team, our goal was to increase sales and web traffic for a company that was not relevant on the internet. One of our main tasks included developing a website and mobile application visitors could access on any device. Developing an online marketing campaign was necessary to attract visitors from outside sources. We would also deploy a team of analytics and data specialists who would be responsible for evaluating keywords and managing an SEO program. This information would be gathered by monitoring user's habits and actions.
Check out more :
http://trumbojz.com/unboxxed/
Ideas that Matter (ItM) is a program that empowers great ideas—changing lives, communities and, ultimately, the world. Ideas that Matter recognizes and supports designers who partner with organizations to bring great ideas to life. More than 19 years, ItM has awarded $13 million in grants that have gone to assist more than 500 charities.  With an Ideas that Matter grant, you will create a campaign that reflects the concerns and needs of the community you live in and care about the most.
Check out more :
SAPPI Ideas that Matter Grant Proposal
Nick Elliott is an up-and-coming electronic dance music DJ, producer and song writer. Focusing his production
skills on EDM with some pop and hip-hop crossover, Elliott draws heavy influences from some of the greats in
the industry like, Skrillex, Afrojack, Calvin Harris, David Guetta, and Avicii.
During the summer of 2019, Nick's management team contacted me regaurding Nick's website. At the time The team did not have a member dedicated to the creation of Nick's online presence. Throughout the remainder of the summer, I assisted in the development of a WordPress site along with corresponding banner graphics, interactive widgets, and a Mailchimp email campaign. For the purpose of this portfolio site, I have taken screenshots of the site after my duties were completed. However, feel free to check out the current site at NickElliott.com.
Check out more :
Nick Elliott's Website
James Madison University is located in the heart of the beautiful mountain city of Harrisonburg, VA. Due to Harrisonburg's diverse population of locals, students, and tourists, the city is able to boast about its modern, yet historic personality. One of the more significant aspects that the city enjoys promoting is eco-friendly behaviors such as recycling. With this in mind, RecycleMe!, has been developed as a mobile application in an attempt to aid residents of Harrisonburg and the surrounding areas with their recycling needs. RecycleMe! performs several tasks such as locating nearby recycling facilities, promoting creative recycling methods via weekly blogs, and encouraging community interaction through an enviro-friendly social media platform.
Check out more :
https://s6443t.axshare.com
To wrap up my second semester as a SMAD student, one of my assignments was directed towards showing off the HTML5 and CSS3 skills that had been obtained in one particular class; Hooked is a knock-off retail site that was developed for this reason. Guidelines of this assignment stated that we were responsible for creating a responsive retail website that would display four pages of content along with a makeshift privacy policy page, and scale to fit the dimensions of three different screen sizes. For my specific submission, I chose to do a mockup of a fishing tackle website by creating a home page that showcased featured sale items, a page specific to models of lures, a page dedicated to rods & reels, and a page where users could view all items on sale. All images have been borrowed from :
tacklewarehouse.com and pexels.com.
Check out more :
http://trumbojz.com/smad307/retail/
Username : trumbo
Password : smad307
Corporate websites often struggle with the challenge of presenting visual messages to a wide variety of target audiences. These target audiences have a wide variety of preferences. The latest approach to meeting this challenge is to build separate "micro" web sites that serve as companions to the main corporate site, but specifically targeted to each demographic. For this project, I created wireframes and mock-up user interface designs of a micro site targeted to college students, and a report to accompany my designs. I based my mock-up on a well known existing web site that does not currently have micro sites.
Check out more :
Microsite Redesign
For this assignment, each individual in the class was required to blog at least once a week regarding an article or media presentation related to that week's topic or topics. We applyied key concepts, terms or ideas learned in class to something found in a newspaper, magazine, book chapter, film, television/radio broadcast, podcast, or other online source. The blog is our space to explore, engage and connect the article or media presentation with the readings and materials shown in class. The requirements were to have each blog posting substantial enough for the reader to understand what the article/presentation is about, but was to be more than simply a summary of its content.
Check out more :
SMAD 407 Blog


Hi! I’m Vincent Dutordoir, a PhD student in Probabilistic Machine Learning at the University of Cambridge, working with professor Zoubin Ghahramani and Carl Henrik Ek.
Prior to my PhD, I worked for a couple of years at Secondmind as a machine learning researcher. I’m still affiliated to Secondmind on a part-time basis since starting my PhD. In fall 2022, I did an internship at DeepMind.
My research focuses on the intersection of statistical methods and deep learning, with applications in generative modelling and sequential decision making. Recently, I have been excited about defining stochastic processes using denoising diffusion models.
Besides my research, I love developing fullstack (data-centric) applications, and I help maintain a couple of opensource projects: 1, 2, 3.
News
- Jun 1, 2023. Very happy to have three papers accepted at ICML 2023 on Neural Diffusion Processes, Memory-based Meta-Learning and Spherical-Orthogonal features.
- Dec 8, 2022. Helped organizing a local NeurIPS meetup in Cambridge.
- Sep 16, 2022. Was invited to give a talk at GeNU 2022 in Copenhagen on diffusion models.
- Sep 14, 2022. Gave a lecture at the Gaussian process summer school in Sheffield on Spectral and Spherical Gaussian processes.
- Sep 1, 2022. Start internship at DeepMind. I’ll be spending the fall in London working on technical analysis of transformer models.
Research
Highlighted research papers. A complete list can be found on my Google scholar.
Neural Diffusion Processes
International Conference on Machine Learning (ICML 2023)
Generative models that define a probabilistic model over functions via their finite marginals using probabilistic diffusion models.
Deep neural networks as point estimates for deep Gaussian processes
Advances in Neural Information Processing Systems (NeurIPS 2021)
Shows the equivalence between the forward propogation of the mean in a Deep Gaussian process (GP) and a fully-connected neural network layer. Method can be used to better initialise deep GPs and understand the uncertainty in DNNs.
Sparse Gaussian Processes with Spherical Harmonic Features
Internation Conference of Machine Learning (ICML 2020)
We derive the Reproducing Kernel Hilbert space for spherical kernels allowing us to design linear time Gausian processes (GPs).
You can find some of my work on Github and a list of all my publications on Google scholar. I’m very happy to connect on Twitter or via e-mail on
<EMAIL_ADDRESS>.


| 1 | package fr.sii.ogham.helper.email; | |
| 2 | ||
| 3 | import java.util.ArrayList; | |
| 4 | import java.util.Arrays; | |
| 5 | import java.util.List; | |
| 6 | ||
| 7 | /** | |
| 8 | * Class used in tests for ensuring that the email is respected. It provides the | |
| 9 | * following information: | |
| 10 | *
 | |
| 11 | *
The expected subject
 | |
| 12 | *
The expected sender address
 | |
| 13 | *
The expected recipients (to, cc, bcc)
 | |
| 14 | *
 | |
| 15 | * | |
| 16 | * @author Aurélien Baudet | |
| 17 | * | |
| 18 | */ | |
| 19 | public class ExpectedEmailHeader { | |
| 20 | /** | |
| 21 | * The expected subject | |
| 22 | */ | |
| 23 | protected String subject; | |
| 24 | | |
| 25 | /** | |
| 26 | * The expected sender address | |
| 27 | */ | |
| 28 | protected String from; | |
| 29 | | |
| 30 | /** | |
| 31 | * The expected list of recipients for the "to" field | |
| 32 | */ | |
| 33 | protected List<String> to = new ArrayList<>(); | |
| 34 | ||
| 35 | /** | |
| 36 | * The expected list of recipients for the "cc" field | |
| 37 | */ | |
| 38 | protected List<String> cc = new ArrayList<>(); | |
| 39 | ||
| 40 | /** | |
| 41 | * The expected list of recipients for the "bcc" field | |
| 42 | */ | |
| 43 | protected List<String> bcc = new ArrayList<>(); | |
| 44 | ||
| 45 | public ExpectedEmailHeader(String subject, String from, String... to) { | |
| 46 | this(subject, from, new ArrayList<>(Arrays.asList(to))); | |
| 47 | } | |
| 48 | ||
| 49 | public ExpectedEmailHeader(String subject, String from, List<String> to) { | |
| 50 | super(); | |
| 51 | this.subject = subject; | |
| 52 | this.from = from; | |
| 53 | this.to = to; | |
| 54 | } | |
| 55 | ||
| 56 | public String getSubject() { | |
| 57 |
3
1. getSubject : All method body replaced by: return "" → NO_COVERAGE 2. getSubject : All method body replaced by: return "A" → NO_COVERAGE 3. getSubject : All methods instructions replaced by: return null; → NO_COVERAGE |
return subject; |
| 58 | } | |
| 59 | ||
| 60 | public String getFrom() { | |
| 61 |
3
1. getFrom : All method body replaced by: return "" → NO_COVERAGE 2. getFrom : All method body replaced by: return "A" → NO_COVERAGE 3. getFrom : All methods instructions replaced by: return null; → NO_COVERAGE |
return from; |
| 62 | } | |
| 63 | ||
| 64 | public List<String> getTo() { | |
| 65 |
1
1. getTo : All methods instructions replaced by: return null; → NO_COVERAGE |
return to; |
| 66 | } | |
| 67 | ||
| 68 | public List<String> getCc() { | |
| 69 |
1
1. getCc : All methods instructions replaced by: return null; → NO_COVERAGE |
return cc; |
| 70 | } | |
| 71 | ||
| 72 | public List<String> getBcc() { | |
| 73 |
1
1. getBcc : All methods instructions replaced by: return null; → NO_COVERAGE |
return bcc; |
| 74 | } | |
| 75 | ||
| 76 | public void setCc(String... cc) { | |
| 77 |
1
1. setCc : All method instructions removed → NO_COVERAGE |
this.cc = new ArrayList<>(Arrays.asList(cc)); |
| 78 | } | |
| 79 | ||
| 80 | public void setBcc(String... bcc) { | |
| 81 |
1
1. setBcc : All method instructions removed → NO_COVERAGE |
this.bcc = new ArrayList<>(Arrays.asList(bcc)); |
| 82 | } | |
| 83 | } | |
Mutations | ||
| 57 |
1.1 2.2 3.3 |
|
| 61 |
1.1 2.2 3.3 |
|
| 65 |
1.1 |
|
| 69 |
1.1 |
|
| 73 |
1.1 |
|
| 77 |
1.1 |
|
| 81 |
1.1 |


THE THIRTEENTH FLOOR A film review by Christopher Null Copyright 1999 Christopher Null filmcritic.com
I want to start by mentioning that I actually work on the 13th floor of a real live building in downtown San Francisco. My business card actually reads `13th Floor'. Reading my business card is more interesting than this film.
Interesting premise: Computer geniuses build a virtual reality machine that lets them go back in time to 1937 Los Angeles. Only the virtual people have feelings and emotions just like us; they don't know they're not real. But then they find out.
Horrible execution: Working from a screenplay from Rusnak and Centeno-Rodriguez – neither of whom have written anything I've ever heard of – and under the direction of Rusnak – whose only English-language credit is as second unit director on GODZILLA, THE THIRTEENTH FLOOR has little to no raw talent behind it. Rusnak obviously couldn't put together a love scene if he was in it himself with Cindy Crawford - the film's little tryst between Bierko and Mol drew howls of laughter from our audience.
On technical merits, FLOOR is an even bigger failure. I haven't seen a film in the last 20 years that has such bad lighting and poor choice of film stock. And I'd be remiss without pointing to the hideously flawed soundtrack on our test print – or maybe it was the theater. (Maybe that was a blessing.)
After two good VR flicks: THE MATRIX and EXISTENZ, I suppose we were ripe for a failure in going for three in a row. You know, in most buildings, the thirteenth floor doesn't exist.
If only we had been so lucky.

The Internet Movie Database accepts no responsibility for the contents of the
review and has no editorial control. Unless stated otherwise, the copyright
belongs to the author.
Please direct comments/criticisms of the review to relevant newsgroups.
Broken URLs inthe reviews are the responsibility of the author.
The formatting of the review is likely to differ from the original due
to ASCII to HTML conversion.
Related links: index of all rec.arts.movies.reviews reviews


|
C++ Actor Framework 0.19
|
Forwards all events to its parent. More...
#include <observer.hpp>
Public Member Functions | |
| forwarder (intrusive_ptr< Parent > parent, Token token) | |
| void | on_complete () override |
| void | on_error (const error &what) override |
| void | on_subscribe (subscription new_sub) override |
| void | on_next (const T &item) override |
| Public Member Functions inherited from caf::flow::observer_impl_base< T > | |
| void | ref_coordinated () const noexcept final |
| void | deref_coordinated () const noexcept final |
| Public Member Functions inherited from caf::detail::plain_ref_counted | |
| plain_ref_counted (const plain_ref_counted &) | |
| plain_ref_counted & | operator= (const plain_ref_counted &) |
| void | ref () const noexcept |
| Increases reference count by one. | |
| void | deref () const noexcept |
Decreases reference count by one and calls request_deletion when it drops to zero. | |
| bool | unique () const noexcept |
| Queries whether there is exactly one reference. | |
| size_t | get_reference_count () const noexcept |
| Queries the current reference count for this object. | |
Additional Inherited Members | |
| Protected Attributes inherited from caf::detail::plain_ref_counted | |
| size_t | rc_ |
Forwards all events to its parent.


09-Jun-2017 | Milku
but these aren't due to politics.
It's Day 9 of 30 Days Wild, a welcome distraction from all the election news. I'm still peeved that I can't vote. No one even showed a picture of a hamster with a polling station. Who wants to see dogs, cats, even a hedgehog! A hamster would make everyone feel a bit better on election day.
Apparently there’s always room in a garden for more plants. And sometimes you don’t even have to plant seeds but can take a short cut and use a bit of a plant to make another. Well, I’m not convinced, but my little humans were so roamed the garden to pick pieces off the jostaberry, rosemary and box bushes. The book that gives us all the outdoors-y sort of ideas actually suggested using lavender, but the girls couldn’t find any of that.
They put some compost into pots and then prepared the cuttings. What they needed was newly grown parts of the plant. They stripped off some of the leaves and cut the bottom of the stem at an angle, just below where a leaf had been growing. The book suggested just putting the cuttings straight into the compost and covering the pot with a bag. But my humans are not great at following instructions. They dipped the stems in rooting compound before they planted them in the soil. And they haven’t bothered covering them up. They’re just outside…exposed to the elements. They’ll be lucky if anything grows.
One of my little humans is heading off to Guide Camp this weekend. So she's sure to be doing something in the great outdoors. I can't wait to hear what the others are going to do.


{undo-redo-buttons.png width=192}
These {_button buttons} in the {_Navigation_bar} invoke the Undo and Redo functions of the Digital Chroma. They also show what changes are next in line for undoing or redoing. This feature makes it really hard to lose any of your program data.
The Digital Chroma records undo information for all edits to the {_current_program}, as well as all changes to stored programs. This even includes bulk changes to stored programs, as a result of importing programs from an external flash drive. (It doesn't include changes made to the flash drive, though.)
As edits are made to the current program, the Digital Chroma doesn't record each tiny change as a separate undoable event. Instead, it combines consecutive edits into a single change until a certain period of inactivity elapses. Other operations, like loading and storing, are always recorded as distinct operations. Loading a bank of programs, or all programs, from a flash drive is treated as a single operation.
You can adjust this time with the {_global_parameter global} edit timeout parameter in the TOOLS {_screen}, but it is initially set to five seconds
When you undo something, the change is moved from the undo list to the redo list, so that you can redo it if you change your mind. This means that you can go back in time to see what your program sounded like earlier, and then go back to the "present" and proceed with your editing.

This is identical to the way undo and redo work in programs like word processors, or the way the Back and Forward buttons work in web browsers (and in this help browser).
Since "doing" anything leaves the redo list empty, you can use Redo to start a new undoable edit operation, rather than waiting for the timeout, if you think you might want to get back to the current state.
You can press R or U on the keyboard to invoke these functions.


Gender Politics, Climate Change Dominate at American Music Awards
Political and cultural topics – from gender politics to climate change – dominated the 2019 American Music Awards performances on Sunday.
by Hannah BleauActivist artists did more than promote their political agendas in grandiose speeches, as is usually custom, during Sunday night’s AMAs at the Microsoft Theater in Los Angeles, as Newsbusters notes. Many opted to advance their causes in more subtle ways – through set design, costumes, and lyrics.
 The “TiK ToK” singer opened the performance by telling the audience, “Welcome to our Sunday Service” – a direct reference to Kanye West’s gospel-filled church services, which have resulted in thousands of people accepting Jesus as their Lord and Savior. A rainbow church set served as a backdrop for the performance.
Pop star Camila Cabello, who won Collaboration of the Year for “Señorita” with singer Shawn Mendes, performed her song “Living Proof,” which featured male dancers wearing lace dresses.
Taylor Swift, who highlighted her newfound devotion to “social justice” in her latest album Lover and won six awards including Artist of the Decade, opened her performance with the song “The Man,” which laments gender double standards.

It is hardly the first time the 17-year-old pop star has spoken out about the climate change “crisis.”
“Our Earth is warming up and our oceans are rising,” Eilish said in a video in September. “Extreme weather is wrecking millions of lives.”


{% extends "base.html" %} {% import "bootstrap/wtf.html" as wtf %} {% import "_macros.html" as macros %} {% block title %}写博客{% endblock %} {% block page_content %}


CBS Releases Its Week 13 College Football Top 10
by Matt HladikWeek 12 of the college football season saw two unbeaten teams fall and a devastating injury for one of the sport’s best players. CBS has unveiled its latest power rankings before Week 13.
Somewhat surprisingly, Dennis Dodd still has Minnesota in his top five, even after the Gophers lost to Iowa. Meanwhile, Oklahoma jumped five spots to No. 6 after beating undefeated Baylor.
LSU, Ohio State, Clemson and Georgia are the current top four for Dodd, and those will be the top four teams when tomorrow’s College Football Playoff rankings are released. Besides that though, expect Dodd’s rankings to look a lot different than the committee’s will.
Here is the full top 10 courtesy of CBS Sports.
- LSU
- Ohio State
- Clemson
- Georgia
- Minnesota
- Oklahoma
- Penn State
- Oregon
- Alabama
- Utah
You can view Dodd’s full top 25 here.
In Week 13, the biggest matchup features Ohio State battling Penn State for the Big Ten East. The last three matchups between these two rivals have been decided by a total of five points.


| Displacement | Engine | Fuel Sysytem |
| 199.5 cc | Triple Spark, 4 - stroke, SOHC - 4V, single cylinder (Liquid Cooled) | Carburettor |
|---|---|---|
| Max Power | Max Torque | Gearbox | 23.17 Bhp @ 9500 rpm | 18.3 Nm @ 8000 rpm | 6 Speed |
| Ground Clearance | Ker/Wet Weight | Fuel Tank Capacity | 167 mm/th> | 153 kg | 12 litres |
| Mileage | Front Brake | Rear Brake | 42 kmpl | 280mm Disc | 230mm Disc |
| Front Suspension | Rear Suspension | Tyre | 37mm Telescopic Front Fork with Antifriction Bush | Nitrox Mono Shock Absorber with piggy back gas canister | 100/80-17" 52P(front),130/70-17" 62P(rear) |
| Displacement | Engine | Fuel Sysytem |
| 197.75 cc | Single cylinder, SI, 4 stroke (Oil Cooled) | Carburettor (KEIHIN CV) / Electronic Fuel Injection |
|---|---|---|
| Max Power | Max Torque | Gearbox | 20.23 BHP (15.09 KW) @ 8500 rpm | 18.1 NM @ 7000 RPM | 5 Speed |
| Ground Clearance | Ker/Wet Weight | Fuel Tank Capacity | 180 mm | 148 kg | 12 litres |
| Mileage | Front Brake | Rear Brake | 35 kmpl | 270mm Petal Disc | 240mm Petal Disc |
| Front Suspension | Rear Suspension | Tyre | 37mm Telescopic Forks | Mono Tube - Monoshock | 90/90 R17 (TVS Remora) [Front],130/70 R17 (TVS Remora)[Rear] with optional Pirelli |
| Displacement | Engine | Fuel Sysytem |
| 219.9 cc | Twin Spark, 2-valve, DTS-i engine (Air Cooled) | Carburettor |
|---|---|---|
| Max Power | Max Torque | Gearbox | 18.8 Bhp @ 8400 rpm (19.03 PS) | 17.5 Nm @ 7000 rpm | 5 Speed |
| Ground Clearance | Ker/Wet Weight | Fuel Tank Capacity | 169 mm/th> | 150 kg | 14 litres |
| Mileage | Front Brake | Rear Brake | 45 kmpl | 260mm Disc | 130mm Drum |
| Front Suspension | Rear Suspension | Tyre | Telescopic with Anti-friction Bush | Twin Shock Absorbers | 90/90 - 17" 49P(front),130/90 - 15" 66P(rear) |
| Displacement | Engine | Fuel Sysytem |
| 220 cc | 4-stroke, DTS-i, single cylinder (Air Cooled) | Carburettor |
|---|---|---|
| Max Power | Max Torque | Gearbox | 20.8 Bhp @ 8500 rpm | 19.12 Nm @ 7000 rpm | 5 Speed |
| Ground Clearance | Ker/Wet Weight | Fuel Tank Capacity | 165 mm/th> | 150 kg | 15 litres |
| Mileage | Front Brake | Rear Brake | 38 kmpl | 260mm Disc, Twin Calipers | 230mm Disc, Single Caliper |
| Front Suspension | Rear Suspension | Tyre | Telescopic, with anti-friction bush | 5 way adjustable, Nitrox shock absorber | 90/90 - 17 - Tubeless(front),120/80 - 17 - Tubeless(rear) |
| Displacement | Engine | Fuel Sysytem |
| 223 cc | 4-Stroke 1-Cylinder OHC (Air Cooled) | Carburettor |
|---|---|---|
| Max Power | Max Torque | Gearbox | 19.2 BHP @ 7500 rpm | 19.35 NM @ 6000 rpm | 5 Speed Manual Transmission |
| Ground Clearance | Ker/Wet Weight | Fuel Tank Capacity | 150 mm | 154 kg | 15 litres |
| Mileage | Front Brake | Rear Brake | 36 kmpl (Approx) | 276mm Disc - Non Asbestos Type | 130mm Drum - Internal Expanding Shoe Type |
| Front Suspension | Rear Suspension | Tyre | Telescopic Hydraulic Shock Absorbers | Swing Arm with 5 Step Adjustable Type Hydraulic | 80 / 100 x 18 - 47 P Tubeless(front)120 / 80 x 18 - 62 P Tubeless (rear) |
| Displacement | Engine | Fuel Sysytem |
| 154.9 cc | 4-stroke, 1-cylinder (Air cooled) | Carburettor |
|---|---|---|
| Max Power | Max Torque | Gearbox | 14.6 BHP @ 8000 rpm | 14 NM @ 6000 rpm | 5 Speed, Manual Transmission |
| Ground Clearance | Ker/Wet Weight | Fuel Tank Capacity | 160 mm | 139 kg | 12 litres |
| Mileage | Front Brake | Rear Brake | 45 kmpl | 266mm Disc | 130mm Drum |
| Front Suspension | Rear Suspension | Tyre | Telescopic | 7-step adjustable rear mono-shock suspension | 100/80-R17(front),140/60-R17(rear) |
| Displacement | Engine | Fuel Sysytem |
| 162.71 cc | 4 Stroke, SI Engine (Air Cooled) | Carburettor |
|---|---|---|
| Max Power | Max Torque | Gearbox | 15.66 BHP @ 8500 rpm | 14.76 NM @ 6500 rpm | 5-speed |
| Ground Clearance | Ker/Wet Weight | Fuel Tank Capacity | 164 mm | 142 kg | 12 litres |
| Mileage | Front Brake | Rear Brake | 45 kmpl | 276mm Disc with a triple-pot Nissin caliper | 220mm Disc with a single-pot Nissin caliper |
| Front Suspension | Rear Suspension | Tyre | Telescopic | Monoshock | 100/80-17 (MRF Zapper FYM)(front),140/70-17 (MRF Zapper FYM)(rear) |
| Displacement | Engine | Fuel Sysytem |
| 177.4 cc | 4-valve, 4 Stroke, Single cylinder (Air Cooled) | UCAL BS-29 |
|---|---|---|
| Max Power | Max Torque | Gearbox | 17.03 Bhp @ 8500 rpm | 15.5 Nm @ 6500 rpm | 5 Speed |
| Ground Clearance | Ker/Wet Weight | Fuel Tank Capacity | 165 mm | 139 kg | 16 litres |
| Mileage | Front Brake | Rear Brake | 45 kmpl | 270mm Petal Disc with RLP | 200mm Petal Disc with RLP |
| Front Suspension | Rear Suspension | Tyre | Telescopic Forks, 105 mm Stroke | Monotube Inverted Gas-filled shox (MIG) with spring aid | 90/90 x 17"(front),110/80 x 17"(rear) |
| Displacement | Engine | Fuel Sysytem |
| 154.9 cc | 4-stroke, 1-cylinder (Air cooled) | Carburettor |
|---|---|---|
| Max Power | Max Torque | Gearbox | 14.6 BHP @ 8000 rpm | 14 NM @ 6000 rpm | 5 Speed, Manual Transmission |
| Ground Clearance | Ker/Wet Weight | Fuel Tank Capacity | 160 mm | 135 kg | 12 litres |
| Mileage | Front Brake | Rear Brake | 50 kmpl | 266mm Disc | 130mm Drum |
| Front Suspension | Rear Suspension | Tyre | Telescopic | Swing Arm, Mono Suspension | 100/80-R17(front), 140/60-R17(rear) |
| Displacement | Engine | Fuel Sysytem |
| 149 cc | 4-stroke, SOHC, 2-valve (Air cooled) | Fuel injection |
|---|---|---|
| Max Power | Max Torque | Gearbox | 12.9 Bhp @ 8000 rpm | 12.8 Nm @ 6000 rpm | 5 Speed Constant mesh |
| Ground Clearance | Ker/Wet Weight | Fuel Tank Capacity | 160 mm/th> | 132 kg | 12 litres |
| Mileage | Front Brake | Rear Brake | 50 kmpl | 267mm Hydraulic disc brake | 130mm Mechanical leading trailing shoe, Drum brake |
| Front Suspension | Rear Suspension | Tyre | Telescopic Forks | Monocross Swingarm | 100/80-17M/C (52P)NYLOGRIP ZAPPER-FX1 (Tubeless)(front),140/60-R17M/C (63P)revz-Y (Tubeless)(rear) |