How to 'implicitly' add some sort of timer for every method of class, excluding constructor and destructor?
What I'm doing now for every method of class:
void MyClass::SomeFunc()
{
cout << __PRETTY_FUNCTION__ <<endl;
boost::timer::cpu_timer timer;
//Some code
boost::timer::cpu_times elapsed = timer.elapsed();
cout << __PRETTY_FUNCTION__ << " : WALLCLOCK TIME: " << elapsed.wall / 1e9 << " seconds" << endl;
}
What I want:
void MyClass::SomeFunc()
{
//Some code
}
assuming behaviour of this two parts of code should be equivalent.
You can almost achieve this using RAII:
struct FunctionLogger {
FunctionLogger(const char* func)
: m_func(func)
{
cout << func <<endl;
}
~FunctionLogger() {
boost::timer::cpu_times elapsed = timer.elapsed();
GSULOG << m_func << " : WALLCLOCK TIME: " << elapsed.wall / 1e9 << " seconds" << endl;
}
const char* m_func;
boost::timer::cpu_timer timer;
};
Now:
void MyClass::SomeFunc()
{
FunctionLogger _(__PRETTY_FUNCTION__);
//Some code
}
And of course if you like macros:
#define FL FunctionLogger _(__PRETTY_FUNCTION__)
void MyClass::SomeFunc()
{
FL;
//Some code
}
If you are looking for an industrial-grade solution for this sort of thing, the term of art is Aspect Oriented Programming. But it's not directly supported by C++.
What you are trying to do is known as known as profiling (getting the duration of each function call) and instrumentation (injecting code into the functions to get more detailed, but probably less accurate, timing information).
By far the best way of doing this is by not doing it yourself, but by running your code under a profiler (an off-the-shelf application which does the timing and, optionally, instrumentation automatically, all without polluting your source code.)
If you want to avoid modifying code, and are willing to sacrifice that __PRETTY_FUNCTION__ output. You can achieve this by accessing the class through a timing handle.
First you define a RAII class for timing, kind of like in John Zwinck's answer:
template<typename T>
struct TimingDecorator {
T *ptr_;
boost::timer::cpu_timer timer;
TimingDecorator (T* ptr) : ptr_(ptr) {}
~TimingDecorator () {
boost::timer::cpu_times elapsed = timer.elapsed();
GSULOG << " : WALLCLOCK TIME: " << elapsed.wall / 1e9 << " seconds" << endl;
}
T* operator->() { return ptr_; }
T const * operator->() const { return ptr_; }
};
Then you define a handle that forces all access to the class through the decorator:
template<typename T>
struct TimingHandle {
T &obj_;
boost::timer::cpu_timer timer;
TimingHandle (T const& obj) : obj_(obj) {}
TimingDecorator<T> operator->() { return &obj_; }
TimingDecorator<T const> operator->() const { return &obj_; }
};
And then for timing you do all access through the handle:
MyClass obj;
TimingHandle<MyClass> obj_timing(obj);
GSULOG << "MyClass::SomeFunc" << endl;
obj_timing->SomeFunc();
I should point out that the last two lines can be wrapped in a macro (if you don't mind using one), to avoid repeating yourself.
#define MYCLASS_TIME_FUNC(handle, func) \
GSULOG << "MyClass::" #func << endl; \
(handle)->func
Which you ultimately can use as
MYCLASS_TIME_FUNC(obj_timing, SomeFunc2)(/* params for SomeFunc2 */);
Reversing the initiatives a bit you can also use:
template <typename Caption, typename F>
auto timed(Caption const& task, F&& f) {
return [f=std::forward<F>(f), task](auto&&... args) {
using namespace std::chrono;
struct measure {
high_resolution_clock::time_point start;
Caption task;
~measure() { GSU_LOCK << " -- (" << task << " completed in " << duration_cast<microseconds>(high_resolution_clock::now() - start).count() << "µs)\n"; }
} timing { high_resolution_clock::now(), task };
return f(std::forward<decltype(args)>(args)...);
};
}
Which you can use like: Live On Coliru
timed_rand = time("Generate a random number", &::rand);
for (int i = 0; i<10; ++i)
std::cout << timed_rand() << " ";
With a bit of MACRO help you can make it even more verstatile to use:
Live On Coliru
#include <iostream>
#include <chrono>
using namespace std::literals::string_literals;
#define GSU_LOG std::clog
template <typename Caption, typename F>
auto timed(Caption const& task, F&& f) {
return [f=std::forward<F>(f), task](auto&&... args) -> decltype(auto) {
using namespace std::chrono;
struct measure {
high_resolution_clock::time_point start;
Caption task;
~measure() { GSU_LOG << " -- (" << task << " completed in " << duration_cast<microseconds>(high_resolution_clock::now() - start).count() << "µs)\n"; }
} timing { high_resolution_clock::now(), task };
return f(std::forward<decltype(args)>(args)...);
};
}
#define TIMED(expr) (timed(__FILE__ + (":" + std::to_string(__LINE__)) + " " #expr, [&]() -> decltype(auto) {return (expr);})())
int main() {
std::string line;
while (TIMED(std::getline(std::cin, line))) {
std::cout << "Simple arithmetic: " << TIMED(42 * TIMED(line.length())) << "\n";
}
}
Prints
$ clang++ -std=c++14 -O2 -Wall -pedantic -pthread main.cpp
$ for a in x xx xxx; do sleep 0.5; echo "$a"; done | ./a.out
-- (main.cpp:25 std::getline(std::cin, line) completed in 497455µs)
-- (main.cpp:26 line.length() completed in 36µs)
-- (main.cpp:26 42 * TIMED(line.length()) completed in 106µs)
Simple arithmetic: 42
-- (main.cpp:25 std::getline(std::cin, line) completed in 503516µs)
-- (main.cpp:26 line.length() completed in 14µs)
-- (main.cpp:26 42 * TIMED(line.length()) completed in 42µs)
Simple arithmetic: 84
-- (main.cpp:25 std::getline(std::cin, line) completed in 508554µs)
-- (main.cpp:26 line.length() completed in 14µs)
-- (main.cpp:26 42 * TIMED(line.length()) completed in 38µs)
Simple arithmetic: 126
-- (main.cpp:25 std::getline(std::cin, line) completed in 286µs)
Note you could also make the lambda accumulate data for different calls and report the totals/average.
Related
I have multiple std::functions that are called on the main thread (not on different threads) in my app (as the result of an asynchronous HTTP requests), for example:
namespace model { struct Order{}; struct Trade{};}
std::function<void (std::string)> func1 = [](std::string http_answer)
{
std::vector<model::Order> orders = ParseOrders(http_answer);
std::cout << "Fetched " << orders.size() << " open/closed orders.");
}
std::function<void (std::string)> func2 = [](std::string http_answer)
{
std::vector<model::Trade> trades = ParseTrades(http_answer);
std::cout << "Fetched " << trades.size() << " trades.");
}
How to call process_result when the both func1 and func2 have parsed HTTP answers?
auto process_result = [](std::vector<model::Order> orders, std::vector<model::Trades> trades)
{
std::cout << "Matching orders and trades.";
};
Is there some solution with co_await or something like this?
You need some kind of synchronization point. Have not used co_await so far so this might not be what you are looking for, however in c++17 I'd go for a std::promise / std::future, maybe like this:
#include <iostream>
#include <functional>
#include <future>
std::promise<std::string> p1;
std::function<void (std::string)> func1 = [](std::string http_answer)
{
// std::vector<model::Order> orders = ParseOrders(http_answer);
// std::cout << "Fetched " << orders.size() << " open/closed orders.");
p1.set_value(http_answer);
};
std::promise<std::string> p2;
std::function<void (std::string)> func2 = [](std::string http_answer)
{
// std::vector<model::Trade> trades = ParseTrades(http_answer);
// std::cout << "Fetched " << trades.size() << " trades.");
p2.set_value(http_answer);
};
int main () {
// whenever that happens...
func1("foo");
func2("bar");
// synchronize on func1 and func2 finished
auto answer1 = p1.get_future().get();
auto answer2 = p2.get_future().get();
auto process_result = [&](/* std::vector<model::Order> orders, std::vector<model::Trades> trades */)
{
std::cout << "Matching orders and trades... " << answer1 << answer2;
};
process_result();
return 0;
}
http://coliru.stacked-crooked.com/a/3c74f00125999fb6
https://en.cppreference.com/w/cpp/thread/future
For now, user-defined literals accept a limited set of types as input parameter (see here). Is there any plan to accept any type as input parameter, and if not why is that ?
For example, I might want to be able to get a std::chrono::duration in different format (seconds, milliseconds, etc), and would do something like
constexpr double operator"" _s(std::chrono::nanosecond time)
{
return std::chrono::duration_cast<std::chrono::duration<double, std::chrono::seconds::period>>(time).count();
}
constexpr long operator"" _us(std::chrono::nanoseconds time)
{
return std::chrono::duration_cast<std::chrono::microseconds>(time).count();
}
// And so on ...
int main()
{
auto t0 = std::chrono::high_resolution_clock::now();
// do some stuff
auto t1 = std::chrono::high_resolution_clock::now();
std::cout << "Time in seconds : " << (t1 - t0)_s << "s\n";
std::cout << "Time in microseconds : " << (t1 - t0)_us << "µs\n";
return 0;
}
Maybe you could make use of helper structs instead:
#include <chrono>
#include <iostream>
using namespace std::literals::chrono_literals;
template <class Duration>
struct dc {
using rep = typename Duration::rep;
const std::chrono::nanoseconds time;
constexpr dc(std::chrono::nanoseconds time):time(time) { }
constexpr operator rep() {
return std::chrono::duration_cast<Duration>(time).count();
}
};
using s_ = dc<std::chrono::seconds>;
using us_ = dc<std::chrono::microseconds>;
// And so on ...
template <us_::rep N>
struct S {
};
int main()
{
auto t0 = std::chrono::high_resolution_clock::now();
// do some stuff
auto t1 = std::chrono::high_resolution_clock::now();
std::cout << "Time in seconds : " << s_(t1 - t0) << "s\n";
std::cout << "Time in microseconds : " << us_(t1 - t0) << "µs\n";
S<us_(10us)> us;
(void)us;
return 0;
}
[live demo]
I have a macro that does exactly what I want it to do:
#define LOG(x)\
do { if (!cpp::app::g_app) {\
ASSERT("CANNOT LOG IF THERE IS NO CPP APP OBJECT" == 0);\
}\
else \
{ \
std::stringstream s; s << cpp::timing::currentDateTime(); s << '\t'; s << x << std::endl; \
*cpp::app::g_app << s.str(); \
cpp::app::g_app->flush(true);\
} \
} while(0)
#endif
Its really nice, because I can:
LOG("On first log line " << 0 << "Still on first log line")
..and a newline is inserted once the LOG macro is done.
Output looks like:
<date / time> On First log line 0 Still on first log line
... subsequent lines here
My question is how to overload << operator on my logging class to do the same?
If I simply overload << operator and return *this (where my logging case can be converted to ostream) then if I do:
mylogger << "First line " << "Still on first line";
then the output is something like:
<date and time> First line
<date and time> Still on first line.
So, I want to emulate the macro behaviour with the << operator. I want a newline automatically when the whole chain of << operations is complete, just like in the macro. But, since macros are evil, I'd rather convert it to a proper function.
Is this achievable?
Edit: Matt's idea about a helper class is quite nice. Based on his suggestion, I made the following disposable helper class:
class log
{
public:
log() :
m_stream(cpp::app::g_app->stream()){
}
template <typename T>
log& operator << (const T& t)
{
m_ss << t;
return *this;
}
virtual ~log(){
m_stream << cpp::timing::currentDateTime() << "\t" << m_ss.str() << "\r\n";
m_stream.flush();
}
private:
std::ostream& m_stream;
std::stringstream m_ss;
};
Use it like:
log() << "All this text" << " will be on one line in the logfile, with date and time prepended ";
log() << "And this lot falls on line 2, with date and time prepended";
I hope that helps Galik and others who may be wanting the same thing.
A small improvement to the solution offered in the question, that creates fewer temporary objects:
class log
{
public:
log() :
m_stream(cpp::app::g_app->stream()){
}
template <typename T>
std::ostream& operator<< (const T& t)
{
return m_stream << cpp::timing::currentDateTime() << "\t" << t;
}
virtual ~log(){
m_stream << "\r\n";
m_stream.flush();
}
private:
std::ostream& m_stream;
};
The temporary instance of log() will be destroyed at the end of the full-expression even if it isn't returned from operator<<. Might as well get rid of the middle-man and the extra stringstream buffer (which btw, doesn't respect the existing formatting options on the main stream -- this could be good or bad)
I have some code that you may find useful.
Its not heavily tested. I am hoping to expand on this to supply a producer/consumer queue which is why I am not using it at the moment. I am still using a macro like you :)
#include <sstream>
#include <memory>
#include <fstream>
#include <iostream>
#include <ctime>
namespace log {
typedef std::stringstream sss; // <3 brevity
class writer
{
private:
std::ostream& sink;
std::string endl = "\n";
std::string get_stamp()
{
time_t rawtime = std::time(0);
tm* timeinfo = std::localtime(&rawtime);
char buffer[32];
std::strftime(buffer, 32, "%Y-%m-%d %H:%M:%S", timeinfo);
return std::string(buffer);
}
public:
writer(std::ostream& sink): sink(sink) {}
void add_line(sss* ss)
{
sink << get_stamp() << " " << ss->rdbuf() << endl;
}
};
// this is used to build the log string in an sts::ostringstream
// which gets std::moved to each new temporary buffer when <<
// is invoked
struct buffer
{
writer& lw;
sss* ss;
buffer(writer& lw): lw(lw), ss(new sss) {}
buffer(const buffer& buf) = delete;
buffer(buffer&& buf): lw(buf.lw), ss(buf.ss) { buf.ss = nullptr; }
~buffer() { if(ss) lw.add_line(ss); delete ss; }
};
// each << creates a new temporary buffer that std::moves
// the std::ostringstream on to the next
template<typename Type>
buffer operator<<(buffer&& buf, const Type& t)
{
(*buf.ss) << t;
return std::move(buf);
}
// A write to a writer creates a temporary buffer and passes
// the << on to that
template<typename Type>
buffer operator<<(writer& lw, const Type& t)
{
return std::move(buffer(lw) << t);
}
} // log
int main()
{
std::ofstream ofs("output.log");
log::writer fout(ofs); // write to file
log::writer lout(std::cout); // write to std output
lout << "A " << 0.7 << " B";
fout << "wibble: " << 2;
}
The way this works is that writing to a log::writer via << causes a temporary log::buffer to be created. Subsequent writes << to the log::buffer create new temporary log::buffer objects which std::move an internal std::ostringstream between them. Because only the final log::buffer object has a non-null std::ostringstream* (because it was std::moved down when it collapsed) it writes the entire line to the log::writer.
My rather simple take on the situation:
class logger{
private:
unsigned int support_count;
std::ostream& output_stream;
public:
logger(std::ostream& str)
:support_count(0),
output_stream(str)
{}
class support_buffer{
private:
logger& l;
support_buffer(logger& l)
:l(l)
{
l.support_count++;
}
public:
support_buffer(const support_buffer& buf)
:l(buf.l)
{
l.support_count++;
}
~support_buffer(){
l.support_count--;
if (l.support_count==0){
l.output_stream << std::endl;
}
}
template <typename T>
support_buffer& operator<<(const T& t){
l.output_stream << t;
return *this;
}
friend class logger;
};
template <typename T>
support_buffer operator<<(const T& t){
output_stream << "<date/time> " << t;
return support_buffer(*this);
}
friend class support_buffer;
};
int main()
{
logger l(std::cout);
l << "Line 1: " << 0 << "Still on line 1";
l << "Line 2";
return 0;
}
Just create a wrapper class that passes all printed elements to our logger and on destruction of the last one send a new line. If you are sure that your output buffer is only being used by your logger class you could even resign of counting support objects. Just print new line character before a line instead of after it.
I'm trying to create a relatively type safe(but dynamic) and efficient concept called "Linkable Properties". A linkable property is similar to C#'s ability to bind properties and such and similar to the signal/slot model.
A linkable property is a type that can link itself to the values of other types. When any value changes all values are updated. This is useful when you need to keep several properties/values updated simultaneously. Once you setup a link everything is taken care of for you.
Can link from any type to any other type (in theory, this is the issue)
Links use a linked list rather than a list. This is more efficient both memory and speed and the real benefit of using this approach.
Converters are used to convert the values from one type to another(from 1, required, also an issue)
Can act like a getter and setter.
The issues I'm struggling with is writing the ability to link and convert to any type. The following code works with minor changes(convert the templated Chain function to a non-templated version and Change Chain<F> to Chain in the SetLink function). The problem is, the links are not correctly called.
This class almost works(it does compile and run but does not work as expected. Without the changes above the binding function never calls. It is only test code and not properly coded(please don't comment about using the static counter, it's just a temporary fix). The Chain and Link elements are the crucial aspect.
Chain is simply suppose to convert and update the value of the property then pass it along(or possibly the original value) to the next property. This continues until one reaches back to the original property in which case it will terminate.
#include <iostream>
#include <string>
#include <boost/bind.hpp>
#include <boost/function.hpp>
using namespace std;
static int iLCount = 1;
template <typename T>
class LinkableProperty
{
public:
std::string Name;
boost::function<void(T)> Link;
T Value;
template<typename F>
void Chain(F val)
{
Value = val;
std::cout << this->Name << " - " << this << ", " << &Link << ", " << val << " ! " << this->Value << " - " << "\n";
if (--iLCount < 0) return;
if (!Link.empty()) Link(Value);
}
LinkableProperty() { Link = NULL; Value = T(); Name = "Level " + std::to_string(iLCount++); };
void operator =(T value) { Value = value; }
template<typename F> void SetLink(LinkableProperty<F> &p)
{
Link = boost::bind(&LinkableProperty<F>::template Chain<F>, &p, _1);
}
void operator ()()
{
if (!Link.empty()) Link(Value);
}
};
int main()
{
LinkableProperty<unsigned short> L1;
LinkableProperty<double> L2;
L2.SetLink(L1);
L1.SetLink(L2);
L1 = 1;
L2 = 1.1;
L1();
cout << "----------\n" << L1.Value << ", " << L2.Value << endl;
getchar();
return 0;
}
The problem most likely stems from here:
template<typename F> void SetLink(LinkableProperty<F> p)
You are passing in a copy of the original property. Change this to accept a reference (or pointer), and you may have better luck. For example:
template<typename F>
void SetLink(LinkableProperty<F>* p)
{
Link = boost::bind(&LinkableProperty<F>::template Chain<F>, p, _1);
}
Should work as expected...
EDIT: Updated to show how to preserve the type across the conversion:
template <typename FT, typename TT>
TT convert(FT v)
{
return v; // default implicit conversion
}
template<>
double convert(unsigned short v)
{
std::cout << "us->d" << std::endl;
return static_cast<double>(v);
}
template<>
unsigned short convert(double v)
{
std::cout << "d->us" << std::endl;
return static_cast<unsigned short>(v);
}
static int iLCount = 1;
template <typename T>
class LinkableProperty
{
template <typename U>
struct _vref
{
typedef U vt;
_vref(vt& v) : _ref(v) {}
U& _ref;
};
public:
std::string Name;
boost::function<void(_vref<T>)> Link;
T Value;
template<typename F>
void Chain(F const& val)
{
Value = convert<typename F::vt, T>(val._ref);
std::cout << this->Name << " - " << this << ", " << &Link << ", " << val._ref << " ! " << this->Value << " - " << "\n";
if (--iLCount < 0) return;
if (!Link.empty()) Link(Value);
}
LinkableProperty() { Link = NULL; Value = T(); Name = "Level " + std::to_string(iLCount++); };
void operator =(T value) { Value = value; }
template<typename F>
void SetLink(LinkableProperty<F>* p)
{
Link = boost::bind(&LinkableProperty<F>::template Chain<_vref<T>>, p, _1);
}
void operator ()()
{
if (!Link.empty()) Link(_vref<T>(Value));
}
};
int main()
{
LinkableProperty<unsigned short> L1;
LinkableProperty<double> L2;
L2.SetLink(&L1);
L1.SetLink(&L2);
L1 = 1;
L2 = 1.1;
L1();
cout << "----------\n" << L1.Value << ", " << L2.Value << endl;
getchar();
return 0;
}
NOTE: There is some link bug which means that the updates trigger more times than necessary - you should check that...
How can I derive a class from cout so that, for example, writing to it
new_cout << "message";
would be equivalent to
cout << __FUNCTION__ << "message" << "end of message" << endl;
class Log
{
public:
Log(const std::string &funcName)
{
std::cout << funcName << ": ";
}
template <class T>
Log &operator<<(const T &v)
{
std::cout << v;
return *this;
}
~Log()
{
std::cout << " [end of message]" << std::endl;
}
};
#define MAGIC_LOG Log(__FUNCTION__)
Hence:
MAGIC_LOG << "here's a message";
MAGIC_LOG << "here's one with a number: " << 5;
#define debug_print(message) (std::cout << __FUNCTION__ << (message) << std::endl)
This has the advantage that you can disable all debug messages at once when you're done
#define debug_print(message) ()
Further from Mykola's response, I have the following implementation in my code.
The usage is
LOG_DEBUG("print 3 " << 3);
prints
DEBUG (f.cpp, 101): print 3 3
You can modify it to use FUNCTION along/in place of LINE and FILE
/// Implements a simple logging facility.
class Logger
{
std::ostringstream os_;
static Logger* instance_;
Logger();
public:
static Logger* getLogger();
bool isDebugEnabled() const;
void log(LogLevelEnum l, std::ostringstream& os, const char* filename, int lineno) const;
std::ostringstream& getStream()
{ return os_; }
};
void Logger::log(LogLevelEnum l, std::ostringstream& os, const char* filename, int lineno) const
{
std::cout << logLevelEnumToString(l) << "\t(" << fileName << ": " << lineno << ")\t- " << os.str();
os.str("");
}
#define LOG_common(level, cptext) do {\
utility::Logger::getLogger()->getStream() << cptext; \
utility::Logger::getLogger()->log(utility::level, utility::Logger::getLogger()->getStream(), __FILE__, __LINE__); \
} while(0);
enum LogLevelEnum {
DEBUG_LOG_LEVEL,
INFO_LOG_LEVEL,
WARN_LOG_LEVEL,
ERROR_LOG_LEVEL,
NOTICE_LOG_LEVEL,
FATAL_LOG_LEVEL
};
#define LOG_DEBUG(cptext) LOG_common(DEBUG_LOG_LEVEL, cptext)
#define LOG_INFO(cptext) LOG_common(INFO_LOG_LEVEL , cptext)
#define LOG_WARN(cptext) LOG_common(WARN_LOG_LEVEL , cptext)
#define LOG_ERROR(cptext) LOG_common(ERROR_LOG_LEVEL, cptext)
#define LOG_NOTICE(cptext) LOG_common(NOTICE_LOG_LEVEL, cptext)
#define LOG_FATAL(cptext) LOG_common(FATAL_LOG_LEVEL, cptext)
const char* logLevelEnumToString(LogLevelEnum m)
{
switch(m)
{
case DEBUG_LOG_LEVEL:
return "DEBUG";
case INFO_LOG_LEVEL:
return "INFO";
case WARN_LOG_LEVEL:
return "WARN";
case NOTICE_LOG_LEVEL:
return "NOTICE";
case ERROR_LOG_LEVEL:
return "ERROR";
case FATAL_LOG_LEVEL:
return "FATAL";
default:
CP_MSG_ASSERT(false, CP_TEXT("invalid value of LogLevelEnum"));
return 0;
}
}
For logging purposes I use something like
#define LOG(x) \
cout << __FUNCTION__ << x << endl
// ...
LOG("My message with number " << number << " and some more");
The problem with your approach is (as Mykola Golybyew explained) that FUNCTION is processed at compile time and would therefore always print the same name with a non-preprocessor solution.
If it's only for adding endl to your messages, you could try something like:
class MyLine {
public:
bool written;
std::ostream& stream;
MyLine(const MyLine& _line) : stream(_line.stream), written(false) { }
MyLine(std::ostream& _stream) : stream(_stream), written(false) { }
~MyLine() { if (!written) stream << "End of Message" << std::endl; }
};
template <class T> MyLine operator<<(MyLine& line, const T& _val) {
line.stream << _val;
line.written = true;
return line;
}
class MyStream {
public:
std::ostream& parentStream;
MyStream(std::ostream& _parentStream) : parentStream(_parentStream) { }
MyLine getLine() { return MyLine(parentStream); }
};
template <class T> MyLine operator<<(MyStream& stream, const T& _val) {
return (stream.getLine() << _val);
}
int main()
{
MyStream stream(std::cout);
stream << "Hello " << 13 << " some more data";
stream << "This is in the next line " << " 1 ";
return 0;
}
Note, that it's important not to return references from the operator functions. Since the MyLine should only exist as a temporary (for its destructor triggers the writing of the endl), the first object (returned by the getLine() function in MyStream) would be destructed before the second operator<< is called. Therefore the MyLine object is copied in each operator<< creating a new one. The last object gets destructed without being written to and writed the end of the message in its destructor.
Just try it out in the debugger to understand whats going on...
You have to override operator<<(), but you even don't have to subclass std::cout. You may also create a new object or use existing objects like that.
You could also override the operator. It will allow you to call another function or prefix/suffix anything that's going to leave the output buffer with whatever you wish: In your case, you'd have it output a specific string.