Несколько недель назад Microsoft презентовал свою новую разработку — проект Casablanca. Для того, чтобы понять что это, нужно вернуться еще чуть дальше в прошлое, к прошедшей конференции Going Native 2012, где помимо обсуждения нового стандарта С++11 было сказано еще немало умных мыслей. Одна из них была в лекции Херба Саттера. Он заметил, что самой большой проблемой современного С++ является не всякие там сборщики мусора или синтаксис лямбда-выражений, а бедность стандартной библиотеки. Когда начинающий программист на Java или C# спрашивает у своего старшего коллеги, как ему послатьпринять HTTP-запрос, распарсить XMLJSON, заархивироватьразархивировать ZIP-файл и т.д. — он получает конкретный, однозначный и работающий всегда ответ: «используй вот этот класс из стандартной библиотеки». Когда начинающий программист на С++ задаёт тот же вопрос — он слышит «ну, стандартных средств для этого нет, нужно или самому писать или вот есть какие-то библиотеки, но тут надо выбирать, тестировать, читать лицензии...». В результате мы имеем дикий зоопарк библиотек с разным уровнем производительности, часто паршивенькой кроссплатформенностью, кучу самописных велосипедов, трудности в переходе между проектами, потому что «раньше я использовал boost, а тут в проекте всё на Qt» и т.д. Херб Саттер высказал мысль, что основное, на чём следует сосредоточиться — это расширение стандартной библиотеки.
Так вот, Microsoft Casablanca — это первый набросок того, как это расширение могло бы выглядеть, что в него могло бы входить и как оно всё вместе могло бы работать. Никто пока не говорит о стандартизации Casablanca как расширения стандартной библиотеки С++, но уже сейчас его можно скачать в виде отдельной библиотеки (что-то вроде альфа-версии) и попробовать поизучать. Кроме того, Microsoft пропагандирует Casablanca как средство создания производительных сервисов для платформы Azure.
Итак, что же входит в Casablanca? Давайте я сразу покажу «Hello world» на Casablanca — это будет веб-сервер, возвращающий текст «Hello World!» на любой запрос к нему:
#include "stdafx.h"
#include <iostream>
#include "astreambuf.h"
using namespace http::listener;
int main(int argc, char* argv[])
{
http_listener::create("http://localhost:4711/trivial", [](http_request message)
{
message.reply(http::status_codes::OK, "Hello World!");
})
/* Prevent Listen() from returning until user hits 'Enter' */
.listen([]() { fgetc(stdin); }).wait();
return 0;
}
Красиво, правда?
А теперь чуть более полно о библиотеке. В неё входят следующие вещи:
PPL tasks
Это библиотека для работы с асинхронными операциями, которая, вообще-то входит в следующую (еще не вышедшую) версию Visual Studio, но разработчики Casablanca решили выделить её отдельно и дать возможность использовать и в Visual Studio 2010. Работает это дело примерно так:
http::http_client client("http://localhost:80");
pplx::task<http::http_response> resp = client.request(methods::GET, "/foo.html");
Здесь мы создали http-клиент для обращения к localhost:80 и задачу «а дай-ка мне методом GET страницу foo.html». Задача начинает выполнятся асинхронно, начиная с момента создания. В любой момент времени мы можем сросить задачу, выполнилась ли она уже:
bool done = resp.is_done();
и попросить результат выполнения:
http_response response = resp.get();
Второй вариант — сразу передать задача лямбда-функцию, которая будет выполнена по её завершению:
resp.then(
[=](http_response response)
{
...
});
Больше о PPL tasks тут
HTTP клиенты и сервера
Два примера выше объясняют вкратце и то, и другое. Добавить к этому можно разве что наличие специальных классов для адресов, заголовков и прочих удобностей. В общем, работа с HTTP становится не сложнее C# или Java, и уж во всяком случае, намного приятнее, чем при использовании входящей нынче в состав Windows библиотека WinInet.
Доступ к Azure Storage Services
Я уже говорил, что одна из основных целей — облегчить создание приложений для Azure. Вот как выглядит процесс сохранения данных в Azure Storage Services
storage_credentials creds = local_storage::get_credentials();
cloud_blob_client local(local_storage::get_blob_uri(), local_storage::get_credentials());
cloud_blob_client real("http://johndoe.blob.core.windows.net", creds);
cloud_blob_container container = client.create_container(L"sampledata").get();
auto blob = container.create_block_blob(L"sample1");
blob.put(L"A first sample blob", L"text/plain");
Весьма лаконично, мне кажется.
JSON
Разбор
std::istream stream = ...;
json::value value1(stream);
double var = value1["var"].as_double()
Создание
json::value::element_vector e;
e.push_back(json::value(false));
e.push_back(json::value::string("hehe"));
json::value arr = json::value::array(e);
std::ostream stream = ...;
stream << arr;
Actors
Идея взята из Erlang. Посылка и обработка сообщений, как дополнительный слой изоляции от внешнего мира. Позволяет проще смотреть на некоторые вещи, избегать багов в многопоточном программировании и вообще есть хорошим паттерном. В примере ниже создаётся Actor, который умеет принимать сообщение и писать его в стандартный вывод.
class Hello : public actors::actor
{
public:
Hello() {}
actors::actor *factory() { new Hello(); }
protected:
void initialize(actors::ActorInitEvent e) { }
virtual void execute() {
std::string name;
accept(name).then([=](std::string &name) {
std::cout << "Hello, " << name << "!" << std::endl;
Done();
});
}
};
...
PID h = actor::spawn<Hello>();
h.send<std::string>("Niklas");
Библиотека еще в разработке и пока очень сырая. Лично мне трудно судить, насколько она приживется. На первый взгляд всё весьма культурно и логично. Архитектура проектировалась с мыслью о кросплатформенности, API открыт, есть стремление открыть код и добавить много полезных вещей. С другой стороны от «просто хорошей библиотеки» до «расширения стандартной библиотеки С++» пропасть шириной до горизонта. В любом случае, ради интереса на Касабланку можно посмотреть.
Материалы по теме
Автор: tangro