|
@@ -0,0 +1,917 @@
|
|
|
+
|
|
|
+ * Copyright (C) 2011-2017 Intel Corporation. All rights reserved.
|
|
|
+ *
|
|
|
+ * Redistribution and use in source and binary forms, with or without
|
|
|
+ * modification, are permitted provided that the following conditions
|
|
|
+ * are met:
|
|
|
+ *
|
|
|
+ * * Redistributions of source code must retain the above copyright
|
|
|
+ * notice, this list of conditions and the following disclaimer.
|
|
|
+ * * Redistributions in binary form must reproduce the above copyright
|
|
|
+ * notice, this list of conditions and the following disclaimer in
|
|
|
+ * the documentation and/or other materials provided with the
|
|
|
+ * distribution.
|
|
|
+ * * Neither the name of Intel Corporation nor the names of its
|
|
|
+ * contributors may be used to endorse or promote products derived
|
|
|
+ * from this software without specific prior written permission.
|
|
|
+ *
|
|
|
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
|
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
|
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
|
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
|
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
|
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
|
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
|
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
|
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
+ *
|
|
|
+ */
|
|
|
+
|
|
|
+#include <string>
|
|
|
+#include <vector>
|
|
|
+#include <iterator>
|
|
|
+#include <typeinfo>
|
|
|
+#include <functional>
|
|
|
+#include <algorithm>
|
|
|
+#include <unordered_set>
|
|
|
+#include <unordered_map>
|
|
|
+#include <initializer_list>
|
|
|
+#include <tuple>
|
|
|
+#include <memory>
|
|
|
+#include <atomic>
|
|
|
+#include <mutex>
|
|
|
+#include <condition_variable>
|
|
|
+#include <map>
|
|
|
+
|
|
|
+#include "../Enclave.h"
|
|
|
+#include "Enclave_t.h"
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+void ecall_lambdas_demo()
|
|
|
+{
|
|
|
+
|
|
|
+ int local_var = 0;
|
|
|
+
|
|
|
+ [] { return true; };
|
|
|
+
|
|
|
+ [&] { return ++local_var; };
|
|
|
+ [&local_var] { return ++local_var; };
|
|
|
+ [&, local_var] { return local_var; };
|
|
|
+
|
|
|
+ [=] { return local_var; };
|
|
|
+ [local_var] { return local_var; };
|
|
|
+ [=, &local_var] { return ++local_var; };
|
|
|
+
|
|
|
+
|
|
|
+ std::vector< int> v { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
|
|
|
+ printf("[Lambdas] Initial array using lambdas: { ");
|
|
|
+
|
|
|
+
|
|
|
+ std::for_each(std::begin(v), std::end(v), [](int elem) { printf("%d ", elem); });
|
|
|
+ printf("}.\n");
|
|
|
+
|
|
|
+
|
|
|
+ auto first_odd_element = std::find_if(std::begin(v), std::end(v), [=](int elem) { return elem % 2 == 1; });
|
|
|
+
|
|
|
+ if (first_odd_element != std::end(v))
|
|
|
+ printf("[Lambdas] First odd element in the array is %d. \n", *first_odd_element);
|
|
|
+ else
|
|
|
+ printf("[Lambdas] No odd element found in the array.\n");
|
|
|
+
|
|
|
+
|
|
|
+ long long number_of_even_elements = std::count_if(std::begin(v), std::end(v), [=](int val) { return val % 2 == 0; });
|
|
|
+ printf("[Lambdas] Number of even elements in the array is %lld.\n", number_of_even_elements);
|
|
|
+
|
|
|
+
|
|
|
+ std::sort(std::begin(v), std::end(v), [](int e1, int e2) {return e2 < e1; });
|
|
|
+
|
|
|
+
|
|
|
+ printf("[Lambdas] Array after sort: { ");
|
|
|
+ std::for_each(std::begin(v), std::end(v), [](int elem) { printf("%d ", elem); });
|
|
|
+ printf("}. \n");
|
|
|
+ printf("\n");
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+void sample_func_auto_demo()
|
|
|
+{
|
|
|
+ printf("[auto] Function sample_func_auto_demo is called. \n");
|
|
|
+}
|
|
|
+
|
|
|
+void ecall_auto_demo()
|
|
|
+{
|
|
|
+ double local_var = 0.0;
|
|
|
+
|
|
|
+ auto a = 7;
|
|
|
+ printf("[auto] Type of a is int. typeid = %s.\n", typeid(a).name());
|
|
|
+
|
|
|
+ const auto b1 = local_var, *b2 = &local_var;
|
|
|
+ printf("[auto] Type of b1 is const double. typeid = %s.\n", typeid(b1).name());
|
|
|
+ printf("[auto] Type of b2 is const double*. typeid = %s.\n", typeid(b2).name());
|
|
|
+ (void)b1;
|
|
|
+ (void)b2;
|
|
|
+
|
|
|
+ auto c = 0, *d = &a;
|
|
|
+ printf("[auto] Type of c is int. typeid = %s.\n", typeid(c).name());
|
|
|
+ printf("[auto] Type of d is int*. typeid = %s.\n", typeid(d).name());
|
|
|
+ (void)c;
|
|
|
+ (void)d;
|
|
|
+
|
|
|
+ auto lambda = [] {};
|
|
|
+ printf("[auto] Type of lambda is [] {}. typeid = %s.\n", typeid(lambda).name());
|
|
|
+ (void)lambda;
|
|
|
+
|
|
|
+ auto func = sample_func_auto_demo;
|
|
|
+ printf("[auto] Type of func is void(__cdecl*)(void). typeid = %s.\n", typeid(func).name());
|
|
|
+ func();
|
|
|
+
|
|
|
+ printf("\n");
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+void ecall_decltype_demo()
|
|
|
+{
|
|
|
+ int a = 0 ;
|
|
|
+ decltype(a) b = 0;
|
|
|
+ printf("[decltype] Type of b is int. typeid = %s.\n", typeid(b).name());
|
|
|
+
|
|
|
+ double c = 0;
|
|
|
+ decltype(a + c) sum = a + c;
|
|
|
+
|
|
|
+ printf("[decltype] Type of sum is double. typeid = %s.\n", typeid(sum).name());
|
|
|
+ (void)sum;
|
|
|
+ (void)b;
|
|
|
+ printf("\n");
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+void ecall_strongly_typed_enum_demo()
|
|
|
+{
|
|
|
+
|
|
|
+ enum class DaysOfWeek : char { MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY };
|
|
|
+
|
|
|
+
|
|
|
+ DaysOfWeek random_day = DaysOfWeek::MONDAY;
|
|
|
+ (void)random_day;
|
|
|
+
|
|
|
+
|
|
|
+ enum class Weekend { SATURDAY, SUNDAY };
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+void ecall_range_based_for_loops_demo()
|
|
|
+{
|
|
|
+ char array_of_letters[] = { 'a','b','c','d' };
|
|
|
+ std::vector<char> vector_of_letters = { 'a','b','c','d' };
|
|
|
+
|
|
|
+ printf("[range_based_for_loops] Using range based for loops to print the content of an array: { ");
|
|
|
+ for (auto elem : array_of_letters)
|
|
|
+ printf("%c ", elem);
|
|
|
+ printf("}. \n");
|
|
|
+
|
|
|
+ printf("[range_based_for_loops] Using range based for loops to print the content of an vector: { ");
|
|
|
+ for (auto elem : vector_of_letters)
|
|
|
+ printf("%c ", elem);
|
|
|
+ printf("}.\n");
|
|
|
+
|
|
|
+ printf("\n");
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+void ecall_static_assert_demo()
|
|
|
+{
|
|
|
+ static_assert(sizeof(int) < sizeof(double), "Error : sizeof(int) < sizeof(double) ");
|
|
|
+ const int a = 0;
|
|
|
+ static_assert(a == 0, "Error: value of a is not 0");
|
|
|
+
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+class Base
|
|
|
+{
|
|
|
+public:
|
|
|
+
|
|
|
+ virtual void f_cannot_be_inherited() final {};
|
|
|
+ Base(const Base &) = delete;
|
|
|
+ Base() = default;
|
|
|
+ virtual void f_must_be_overrided() {};
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
+class Derived : Base
|
|
|
+{
|
|
|
+public:
|
|
|
+
|
|
|
+ The function cannot be override because it is declared with keyword final in base
|
|
|
+ virtual double f_cannot_be_inherited() {};
|
|
|
+ */
|
|
|
+
|
|
|
+
|
|
|
+ virtual void f_must_be_overrided() override {};
|
|
|
+};
|
|
|
+
|
|
|
+void ecall_virtual_function_control_demo()
|
|
|
+{
|
|
|
+
|
|
|
+ Base a;
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+class DemoDelegatingConstructors
|
|
|
+{
|
|
|
+ int a, b, c;
|
|
|
+public:
|
|
|
+ DemoDelegatingConstructors(int param_a, int param_b, int param_c)
|
|
|
+ {
|
|
|
+ this->a = param_a;
|
|
|
+ this->b = param_b;
|
|
|
+ this->c = param_c;
|
|
|
+
|
|
|
+ switch (c)
|
|
|
+ {
|
|
|
+ case 1:
|
|
|
+ printf("[delegating constructors] Called from DemoDelegatingConstructors(int a, int b). \n");
|
|
|
+ break;
|
|
|
+ case 2:
|
|
|
+ printf("[delegating constructors] Called from DemoDelegatingConstructors(int a). \n");
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ printf("[delegating constructors] Called from DemoDelegatingConstructors(int a, int b, int c).\n");
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ DemoDelegatingConstructors(int param_a, int param_b) : DemoDelegatingConstructors(param_a, param_b, 1) {}
|
|
|
+ DemoDelegatingConstructors(int param_a) : DemoDelegatingConstructors(param_a, 0, 2) {}
|
|
|
+};
|
|
|
+
|
|
|
+void ecall_delegating_constructors_demo()
|
|
|
+{
|
|
|
+ DemoDelegatingConstructors a(1, 2, 3);
|
|
|
+ DemoDelegatingConstructors b(1, 2);
|
|
|
+ DemoDelegatingConstructors c(1);
|
|
|
+
|
|
|
+ printf("\n");
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+void sample_std_function1()
|
|
|
+{
|
|
|
+ printf("[std_function] calling sample_std_function1\n");
|
|
|
+}
|
|
|
+
|
|
|
+void ecall_std_function_demo()
|
|
|
+{
|
|
|
+
|
|
|
+ std::function<void()> funct = sample_std_function1;
|
|
|
+ funct();
|
|
|
+
|
|
|
+
|
|
|
+ std::function<void()> funct_lambda = [] { printf("[std_function] calling a lambda function\n"); };
|
|
|
+ funct_lambda();
|
|
|
+
|
|
|
+ printf("\n");
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+void ecall_cxx11_algorithms_demo()
|
|
|
+{
|
|
|
+ std::vector<int> v = { 0, 1, 2, 3, 4, 5 };
|
|
|
+ bool are_all_of = all_of(begin(v), end(v), [](int e) { return e % 2 == 0; });
|
|
|
+ printf("[cxx11_algorithms] All elements in { 0 1 2 3 4 5 } are even is %s. \n", are_all_of ? "true" : "false");
|
|
|
+
|
|
|
+ bool are_any_of = any_of(begin(v), end(v), [](int e) { return e % 2 == 0; });
|
|
|
+ printf("[cxx11_algorithms] Some elements in { 0 1 2 3 4 5 } are even is %s. \n", are_any_of ? "true" : "false");
|
|
|
+
|
|
|
+ bool are_none_of = none_of(begin(v), end(v), [](int e) { return e % 2 == 0; });
|
|
|
+ printf("[cxx11_algorithms] Some elements in { 0 1 2 3 4 5 } are even is %s. \n", are_none_of ? "true" : "false");
|
|
|
+
|
|
|
+ printf("\n");
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+template<typename T>
|
|
|
+T sum(T elem)
|
|
|
+{
|
|
|
+ return elem;
|
|
|
+}
|
|
|
+
|
|
|
+template<typename T, typename... Args>
|
|
|
+T sum(T elem1, T elem2, Args... args)
|
|
|
+{
|
|
|
+ return elem1 + elem2 + sum(args...);
|
|
|
+}
|
|
|
+
|
|
|
+void ecall_variadic_templates_demo()
|
|
|
+{
|
|
|
+ int computed_sum = sum(1, 2, 3, 4, 5);
|
|
|
+ printf("[variadic_templates] The sum of paramters (1, 2, 3, 4, 5) is %d. \n", computed_sum);
|
|
|
+ printf("\n");
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+template <typename T> void f(typename T::A*) { printf("[sfinae] First candidate for substitution is matched.\n"); };
|
|
|
+
|
|
|
+
|
|
|
+template <typename T> void f(T) { printf("[sfinae] Second candidate for substitution is matched.\n"); }
|
|
|
+
|
|
|
+void ecall_SFINAE_demo()
|
|
|
+{
|
|
|
+ f<int>(0x0);
|
|
|
+ printf("\n");
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+class Number
|
|
|
+{
|
|
|
+public:
|
|
|
+ Number(const std::initializer_list<int> &v) {
|
|
|
+ for (auto i : v) {
|
|
|
+ elements.push_back(i);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ void print_elements() {
|
|
|
+ printf("[initializer_list] The elements of the vector are:");
|
|
|
+ for (auto item : elements) {
|
|
|
+ printf(" %d", item);
|
|
|
+ }
|
|
|
+ printf(".\n");
|
|
|
+ }
|
|
|
+private:
|
|
|
+ std::vector<int> elements;
|
|
|
+};
|
|
|
+
|
|
|
+void ecall_initializer_list_demo()
|
|
|
+{
|
|
|
+ printf("[initializer_list] Using initializer list in the constructor. \n");
|
|
|
+ Number m = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
|
|
|
+ m.print_elements();
|
|
|
+
|
|
|
+ printf("\n");
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+class DemoBuffer
|
|
|
+{
|
|
|
+public:
|
|
|
+ unsigned int size = 100;
|
|
|
+ char *buffer;
|
|
|
+
|
|
|
+ DemoBuffer(int param_size)
|
|
|
+ {
|
|
|
+ this->size = param_size;
|
|
|
+ buffer = new char[size];
|
|
|
+ printf("[rvalue] Called constructor : DemoBuffer(int size).\n");
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ DemoBuffer(const DemoBuffer & rhs)
|
|
|
+ {
|
|
|
+ this->size = rhs.size;
|
|
|
+ buffer = new char[rhs.size];
|
|
|
+ memcpy(buffer, rhs.buffer, size);
|
|
|
+ printf("[rvalue] Called copy constructor : DemoBuffer(const DemoBuffer & rhs).\n");
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ DemoBuffer(DemoBuffer && rhs)
|
|
|
+ {
|
|
|
+ buffer = rhs.buffer;
|
|
|
+ size = rhs.size;
|
|
|
+
|
|
|
+ rhs.buffer = NULL;
|
|
|
+ rhs.size = 0;
|
|
|
+ printf("[rvalue] Called move constructor : DemoBuffer(DemoBuffer && rhs).\n");
|
|
|
+ }
|
|
|
+ ~DemoBuffer()
|
|
|
+ {
|
|
|
+ delete buffer;
|
|
|
+ }
|
|
|
+
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
+DemoBuffer foobar(int a)
|
|
|
+{
|
|
|
+ DemoBuffer x(100);
|
|
|
+ DemoBuffer y(100);
|
|
|
+
|
|
|
+ if (a > 0)
|
|
|
+ return x;
|
|
|
+ else
|
|
|
+ return y;
|
|
|
+}
|
|
|
+void ecall_rvalue_demo()
|
|
|
+{
|
|
|
+
|
|
|
+ printf("[rvalue] DemoBuffer a(100).\n");
|
|
|
+ DemoBuffer a(100);
|
|
|
+
|
|
|
+ printf("[rvalue] DemoBuffer foobar(100). \n");
|
|
|
+
|
|
|
+
|
|
|
+ DemoBuffer d(foobar(100));
|
|
|
+
|
|
|
+
|
|
|
+ printf("[rvalue] DemoBuffer b(a).\n");
|
|
|
+ DemoBuffer b(a);
|
|
|
+
|
|
|
+ printf("[rvalue] DemoBuffer c(std::move(a)).\n");
|
|
|
+
|
|
|
+
|
|
|
+ DemoBuffer c(std::move(a));
|
|
|
+
|
|
|
+ printf("\n");
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+void nullptr_overload_candidate(int i) {
|
|
|
+ (void)i;
|
|
|
+ printf("[nullptr] called void nullptr_overload_candidate(int i).\n");
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+void nullptr_overload_candidate(int* ptr) {
|
|
|
+ (void)ptr;
|
|
|
+ printf("[nullptr] called void nullptr_overload_candidate(int* ptr).\n");
|
|
|
+}
|
|
|
+
|
|
|
+template<class F, class A>
|
|
|
+void Fwd(F f, A a)
|
|
|
+{
|
|
|
+ f(a);
|
|
|
+}
|
|
|
+
|
|
|
+void g(int* i)
|
|
|
+{
|
|
|
+ (void)i;
|
|
|
+ printf("[nullptr] Function %s called\n", __FUNCTION__);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+void ecall_nullptr_demo()
|
|
|
+{
|
|
|
+
|
|
|
+ nullptr_overload_candidate(NULL);
|
|
|
+
|
|
|
+
|
|
|
+ nullptr_overload_candidate(nullptr);
|
|
|
+
|
|
|
+ g(NULL);
|
|
|
+ g(0);
|
|
|
+ Fwd(g, nullptr);
|
|
|
+
|
|
|
+
|
|
|
+ printf("\n");
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+enum class Color { orange, brown, green = 30, blue, red };
|
|
|
+
|
|
|
+void ecall_enum_class_demo()
|
|
|
+{
|
|
|
+ int n = 0;
|
|
|
+ Color color1 = Color::brown;
|
|
|
+ switch (color1)
|
|
|
+ {
|
|
|
+ case Color::orange: printf("[enum class] orange"); break;
|
|
|
+ case Color::brown: printf("[enum class] brown"); break;
|
|
|
+ case Color::green: printf("[enum class] green"); break;
|
|
|
+ case Color::blue: printf("[enum class] blue"); break;
|
|
|
+ case Color::red: printf("[enum class] red"); break;
|
|
|
+ }
|
|
|
+
|
|
|
+ n = static_cast<int>(color1);
|
|
|
+ printf(" - int = %d\n", n);
|
|
|
+
|
|
|
+ Color color2 = Color::red;
|
|
|
+ switch (color2)
|
|
|
+ {
|
|
|
+ case Color::orange: printf("[enum class] orange"); break;
|
|
|
+ case Color::brown: printf("[enum class] brown"); break;
|
|
|
+ case Color::green: printf("[enum class] green"); break;
|
|
|
+ case Color::blue: printf("[enum class] blue"); break;
|
|
|
+ case Color::red: printf("[enum class] red"); break;
|
|
|
+ }
|
|
|
+ n = static_cast<int>(color2);
|
|
|
+ printf(" - int = %d\n", n);
|
|
|
+
|
|
|
+ Color color3 = Color::green;
|
|
|
+ switch (color3)
|
|
|
+ {
|
|
|
+ case Color::orange: printf("[enum class] orange"); break;
|
|
|
+ case Color::brown: printf("[enum class] brown"); break;
|
|
|
+ case Color::green: printf("[enum class] green"); break;
|
|
|
+ case Color::blue: printf("[enum class] blue"); break;
|
|
|
+ case Color::red: printf("[enum class] red"); break;
|
|
|
+ }
|
|
|
+ n = static_cast<int>(color3);
|
|
|
+ printf(" - int = %d\n", n);
|
|
|
+ printf("\n");
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+void ecall_new_container_classes_demo()
|
|
|
+{
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ std::unordered_set<int> set_of_numbers = { 0, 1, 2, 3, 4, 5 };
|
|
|
+ const int searchVal = 3;
|
|
|
+ std::unordered_set<int>::const_iterator got = set_of_numbers.find(searchVal);
|
|
|
+
|
|
|
+ if (got == set_of_numbers.end())
|
|
|
+ printf("[new_container_classes] unordered_set { 0, 1, 2, 3, 4, 5} has value 3.\n");
|
|
|
+ else
|
|
|
+ printf("[new_container_classes] unordered_set { 0, 1, 2, 3, 4, 5} it does not have value 3.\n");
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ std::unordered_multiset<int> multiset_of_numbers = { 0, 1, 2, 3, 3, 3 };
|
|
|
+ printf("[new_container_classes] multiset_set { 0, 1, 2, 3, 3, 3} has %d elements with value %d.\n",
|
|
|
+ (int)multiset_of_numbers.count(searchVal), searchVal);
|
|
|
+
|
|
|
+
|
|
|
+ std::unordered_map<std::string, int> grades{ { "A", 10 },{ "B", 8 },{ "C", 7 },{ "D", 5 },{ "E", 3 } };
|
|
|
+ printf("[new_container_classes] unordered_map elements: {");
|
|
|
+ for (auto pair : grades) {
|
|
|
+ printf("[%s %d] ", pair.first.c_str(), pair.second);
|
|
|
+ }
|
|
|
+
|
|
|
+ printf("}.\n");
|
|
|
+
|
|
|
+
|
|
|
+ std::unordered_multimap<std::string, int> multimap_grades{ { "A", 10 },{ "B", 8 },{ "B", 7 },{ "E", 5 },{ "E", 3 },{ "E",1 } };
|
|
|
+
|
|
|
+ printf("[new_container_classes] unordered_multimap elements: {");
|
|
|
+ for (auto pair : multimap_grades) {
|
|
|
+ printf("[%s %d] ", pair.first.c_str(), pair.second);
|
|
|
+ }
|
|
|
+ printf("}.\n");
|
|
|
+
|
|
|
+ printf("\n");
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+void ecall_tuple_demo()
|
|
|
+{
|
|
|
+
|
|
|
+ char array_of_letters[4] = {'A','B','C','D'};
|
|
|
+ std::vector<char> vector_of_letters = { 'A','B','C','D' };
|
|
|
+ std::map<char, char> map_of_letters = { {'B','b' } };
|
|
|
+
|
|
|
+
|
|
|
+ std::tuple<int, std::string> tuple_sample_with_constructor(42, "Sample tuple");
|
|
|
+ (void)tuple_sample_with_constructor;
|
|
|
+
|
|
|
+
|
|
|
+ auto tuple_sample = std::make_tuple("<First element of TupleSample>", 1, 7.9, vector_of_letters, array_of_letters, map_of_letters);
|
|
|
+
|
|
|
+
|
|
|
+ printf("[tuple] show first element in TupleSample: %s. \n", std::get<0>(tuple_sample));
|
|
|
+ printf("[tuple] show second element in TupleSample: %d. \n", std::get<1>(tuple_sample));
|
|
|
+ printf("[tuple] show third element in TupleSample: %f. \n", std::get<2>(tuple_sample));
|
|
|
+
|
|
|
+
|
|
|
+ std::vector<char> temp_vector = std::get<3>(tuple_sample);
|
|
|
+ (void)temp_vector;
|
|
|
+
|
|
|
+
|
|
|
+ int first_elem_of_array = std::get<4>(tuple_sample)[0];
|
|
|
+ (void)first_elem_of_array;
|
|
|
+
|
|
|
+
|
|
|
+ std::map<char, char> temp_map = std::get<5>(tuple_sample);
|
|
|
+ (void)temp_map;
|
|
|
+ printf("\n");
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+class DemoSmartPtr
|
|
|
+{
|
|
|
+ std::string smartPointerType;
|
|
|
+public:
|
|
|
+ DemoSmartPtr(std::string param_smartPointerType)
|
|
|
+ {
|
|
|
+ printf("[smart_ptr] In construct of object demo_smart_ptr using %s. \n", param_smartPointerType.c_str());
|
|
|
+ this->smartPointerType = param_smartPointerType;
|
|
|
+ }
|
|
|
+ ~DemoSmartPtr()
|
|
|
+ {
|
|
|
+ printf("[smart_ptr] In deconstructor of object demo_smart_ptr using %s. \n", smartPointerType.c_str());
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+void ecall_shared_ptr_demo()
|
|
|
+{
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ auto shared_ptr = std::make_shared<DemoSmartPtr>("smart_ptr.");
|
|
|
+
|
|
|
+ printf("[smart_ptr] shared_ptr reference count = %ld. \n", shared_ptr.use_count());
|
|
|
+ auto shared_ptr2 = shared_ptr;
|
|
|
+ printf("[smart_ptr] shared_ptr reference count = %ld incresead after creating another shared pointer.\n", shared_ptr.use_count());
|
|
|
+ shared_ptr2.reset();
|
|
|
+ printf("[smart_ptr] shared_ptr reference count = %ld decresead after calling releasing ownership. \n", shared_ptr.use_count());
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ std::unique_ptr<DemoSmartPtr> unique_ptr(new DemoSmartPtr("unique_ptr"));
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+void ecall_atomic_demo()
|
|
|
+{
|
|
|
+ printf("[atomic] Atomic types, objects and functions demo.\n");
|
|
|
+
|
|
|
+ printf("[atomic_store] Defining an atomic_char object with an initial value of 5.\n");
|
|
|
+ std::atomic_char atc(5);
|
|
|
+ printf("[atomic_store] The current value stored in the atomic object is: %d\n", atc.load());
|
|
|
+ printf("[atomic_store] Replacing the value of the atomic object with a non-atomic value of 3.\n");
|
|
|
+ std::atomic_store<char>(&atc, 3);
|
|
|
+ printf("[atomic_store] The new value of the atomic object is: %d.\n", atc.load());
|
|
|
+
|
|
|
+ printf("\n");
|
|
|
+
|
|
|
+ printf("[atomic_store_explicit] Defining an atomic_short object with an initial value of 5.\n");
|
|
|
+ std::atomic_short ats(5);
|
|
|
+ printf("[atomic_store_explicit] The current value stored in the atomic object is: %d.\n", ats.load());
|
|
|
+ printf("[atomic_store_explicit] Replacing the value of the atomic object with a non-atomic value of 3.\n");
|
|
|
+ std::atomic_store_explicit<short>(&ats, 3, std::memory_order_seq_cst);
|
|
|
+ printf("[atomic_store] The new value of the atomic object is: %d.\n", ats.load());
|
|
|
+
|
|
|
+ printf("\n");
|
|
|
+
|
|
|
+ printf("[atomic_load] Defining an atomic_int object with an initial value of 4.\n");
|
|
|
+ std::atomic_int ati1(4);
|
|
|
+ printf("[atomic_load] Obtaining the value of the atomic object and saving it in a int variable.\n");
|
|
|
+ int val = std::atomic_load(&ati1);
|
|
|
+ printf("[atomic_load] The obtained value is %d.\n", val);
|
|
|
+
|
|
|
+ printf("\n");
|
|
|
+
|
|
|
+ printf("[atomic_load_explicit] Defining an atomic_int object with an initial value of 2.\n");
|
|
|
+ std::atomic_int ati2(2);
|
|
|
+ printf("[atomic_load_explicit] Obtaining the value of the atomic object and saving it in a int variable.\n");
|
|
|
+ int val1 = std::atomic_load_explicit(&ati2, std::memory_order_seq_cst);
|
|
|
+ printf("[atomic_load_explicit] The obtained value is %d.\n", val1);
|
|
|
+
|
|
|
+ printf("\n");
|
|
|
+
|
|
|
+ printf("[atomic_fetch_add] Defining an atomic_int object with an initial value of 7.\n");
|
|
|
+ std::atomic_int ati(7);
|
|
|
+ printf("[atomic_fetch_add] The current value stored in the atomic object is: %d.\n", ati.load());
|
|
|
+ printf("[atomic_fetch_add] Adding a non-atomic value of 8 to the atomic object.\n");
|
|
|
+ std::atomic_fetch_add(&ati, 8);
|
|
|
+ printf("[atomic_fetch_add] The new value of the atomic object is: %d.\n", ati.load());
|
|
|
+
|
|
|
+ printf("\n");
|
|
|
+
|
|
|
+ printf("[atomic_fetch_add_explicit] Defining an atomic_uint object with an initial value of 7.\n");
|
|
|
+ std::atomic_uint atui(7);
|
|
|
+ printf("[atomic_fetch_add_explicit] The current value stored in the atomic object is: %u.\n", atui.load());
|
|
|
+ printf("[atomic_fetch_add_explicit] Adding a non-atomic value of 8 to the atomic object.\n");
|
|
|
+ std::atomic_fetch_add_explicit<unsigned int>(&atui, 8, std::memory_order_seq_cst);
|
|
|
+ printf("[atomic_fetch_add_explicit] The new value of the atomic object is: %u.\n", atui.load());
|
|
|
+
|
|
|
+ printf("\n");
|
|
|
+
|
|
|
+ printf("[atomic_fetch_sub] Defining an atomic_long object with an initial value of 20.\n");
|
|
|
+ std::atomic_long atl(20);
|
|
|
+ printf("[atomic_fetch_sub] The current value stored in the atomic object is: %ld.\n", atl.load());
|
|
|
+ printf("[atomic_fetch_sub] Substracting a non-atomic value of 8 from the value of the atomic object.\n");
|
|
|
+ std::atomic_fetch_sub<long>(&atl, 8);
|
|
|
+ printf("[atomic_fetch_sub] The new value of the atomic object is: %ld.\n", atl.load());
|
|
|
+
|
|
|
+ printf("\n");
|
|
|
+
|
|
|
+ printf("[atomic_fetch_sub_explicit] Defining an atomic_llong object with an initial value of 20.\n");
|
|
|
+ std::atomic_llong atll(20);
|
|
|
+ printf("[atomic_fetch_sub_explicit] The current value stored in the atomic object is: %lld.\n", atll.load());
|
|
|
+ printf("[atomic_fetch_sub_explicit] Substracting a non-atomic value of 8 from the value of the atomic object.\n");
|
|
|
+ std::atomic_fetch_sub_explicit<long long>(&atll, 8, std::memory_order_seq_cst);
|
|
|
+ printf("[atomic_fetch_sub_explicit] The new value of the atomic object is: %lld.\n", atll.load());
|
|
|
+
|
|
|
+ printf("\n");
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+struct CounterWithoutMutex {
|
|
|
+ int value;
|
|
|
+
|
|
|
+ CounterWithoutMutex() : value(0) {}
|
|
|
+
|
|
|
+ void increment() {
|
|
|
+ ++value;
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+CounterWithoutMutex counter_without_protection;
|
|
|
+
|
|
|
+
|
|
|
+void ecall_mutex_demo_no_protection()
|
|
|
+{
|
|
|
+ for (int i = 0; i < 100000; ++i) {
|
|
|
+ counter_without_protection.increment();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+void ecall_print_final_value_no_protection()
|
|
|
+{
|
|
|
+ printf("[mutex] Incrementing values in three threads without mutex protection, using a 100000 times loop. \n[mutex]Expected value is 300000. The final value is %d.\n", counter_without_protection.value);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+struct CounterProtectedByMutex {
|
|
|
+ std::mutex mutex;
|
|
|
+ int value;
|
|
|
+
|
|
|
+ CounterProtectedByMutex() : value(0) {}
|
|
|
+
|
|
|
+ void increment() {
|
|
|
+
|
|
|
+ mutex.lock();
|
|
|
+ ++value;
|
|
|
+
|
|
|
+ mutex.unlock();
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+CounterProtectedByMutex counter_with_protection;
|
|
|
+
|
|
|
+
|
|
|
+void ecall_mutex_demo()
|
|
|
+{
|
|
|
+ for (int i = 0; i < 100000; ++i) {
|
|
|
+ counter_with_protection.increment();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+void ecall_print_final_value_mutex_demo()
|
|
|
+{
|
|
|
+ printf("[mutex] Mutex protection when incrementing a value in 3 threads, using a 100000 times loop. \n[mutex]Expected value is 300000. The final value is %d.\n", counter_with_protection.value);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+class DemoConditionVariable
|
|
|
+{
|
|
|
+ std::mutex mtx;
|
|
|
+ std::condition_variable cond_var;
|
|
|
+ bool data_loaded;
|
|
|
+public:
|
|
|
+ DemoConditionVariable()
|
|
|
+ {
|
|
|
+ data_loaded = false;
|
|
|
+ }
|
|
|
+ void load_data()
|
|
|
+ {
|
|
|
+
|
|
|
+ printf("[condition_variable] Loading Data...\n");
|
|
|
+ {
|
|
|
+
|
|
|
+ std::lock_guard<std::mutex> guard(mtx);
|
|
|
+
|
|
|
+ data_loaded = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ cond_var.notify_one();
|
|
|
+ }
|
|
|
+ bool is_data_loaded()
|
|
|
+ {
|
|
|
+ return data_loaded;
|
|
|
+ }
|
|
|
+ void main_task()
|
|
|
+ {
|
|
|
+ printf("\n");
|
|
|
+ printf("[condition_variable] Running condition variable demo.\n");
|
|
|
+
|
|
|
+
|
|
|
+ std::unique_lock<std::mutex> lck(mtx);
|
|
|
+
|
|
|
+ printf("[condition_variable] Waiting for the data to be loaded in the other thread.\n");
|
|
|
+ cond_var.wait(lck, std::bind(&DemoConditionVariable::is_data_loaded, this));
|
|
|
+ printf("[condition_variable] Processing the loaded data.\n");
|
|
|
+ printf("[condition_variable] Done.\n");
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
+DemoConditionVariable app;
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+void ecall_condition_variable_run()
|
|
|
+{
|
|
|
+ app.main_task();
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+void ecall_condition_variable_load()
|
|
|
+{
|
|
|
+ app.load_data();
|
|
|
+}
|