Mar 27, 2024

[C++] compare_exchange_weak / compare_exchange_strong and why spuriously fail happens

reference:
compare_exchange_weak / compare_exchange_strong

compare_exchange_strong; no spuriously fail


compare_exchange_weak; spuriously fail due to using timed lock; compare_exchange_weak is useful inside a loop;



Mar 13, 2024

[DB study] Serializable Snapshot Isolation (SSI) and write skew; how Spanner works.

Reference:
Serializable Snapshot Isolation in PostgreSQL paper 
A Read-Only Transaction Anomaly Under Snapshot Isolation paper
A Critique of ANSI SQL Isolation Levels paper

Two main properties that characterize Snapshot Isolation:

  1. A transaction in Snapshot Isolation has two significant timestamps: the one at which it performs its reads, and the one at which it performs its writes. The read timestamp defines the “consistent snapshot” of the database the transaction sees. If someone else commits writes at a point after a transaction T’s read timestamp, T will not see those changes (this is generally enforced using MVCC. We’ll refer to a transaction named “x” as Tx and its read and write timestamps as Rx and Wx, respectively.
  2. Two transactions are concurrent if the intervals during which they are executing overlap (R1 < W2 and W1 > R2). In Snapshot Isolation, the database enforces that two committed transactions which are concurrent have disjoint write sets (meaning they don’t write to any of the same memory locations). Any transaction whose commit would cause this restriction to be violated is forced to abort and be retried.

Consider two transactions, P and Q. P copies the value in a register x to y, and Q copies the value in a register y to x. There are only two serial executions of these two, P, Q or Q, P. In either, the end result is that x = y. However, Snapshot Isolation allows for another outcome:
  • Transaction P reads x
  • Transaction Q reads y
  • Transaction P writes the value it read to y
  • Transaction Q writes the value it read to x
This is valid in Snapshot Isolation: each transaction maintained a consistent view of the database and its write set didn’t overlap with any concurrent transaction’s write set. Despite this, x and y have been swapped, an outcome not possible in either serial execution.


Conceptually, there are three types of conflicts: 
  • wr-conflicts (Dirty Reads)
  • ww-conflicts (Lost Updates)
  • rw-conflicts.
PostgreSQL SSI data structure:
  • SIREAD locks
    • An SIREAD lock, internally called a predicate lock, is a pair of an object and (virtual) txids that store information about who has accessed which object.
  • rw-conflicts
    • A rw-conflict is a triplet of an SIREAD lock and two txids that reads and writes the SIREAD lock. The CheckForSerializableConflictIn function is invoked whenever either an INSERT, UPDATE, or DELETE command is executed in SERIALIZABLE mode, and it creates rw-conflicts when detecting conflicts by checking SIREAD locks.


SQL syntax:

[DB study] Serializable vs. Snapshot Isolation Level

Reference:
https://techcommunity.microsoft.com/t5/sql-server-blog/serializable-vs-snapshot-isolation-level/ba-p/383281




Mar 6, 2024

[C++] avoid tail call based on different compiler


// BLOCK_TAIL_CALL_OPTIMIZATION
//
// Instructs the compiler to avoid optimizing tail-call recursion. This macro is
// useful when you wish to preserve the existing function order within a stack
// trace for logging, debugging, or profiling purposes.
//
// Example:
//
//   int f() {
//     int result = g();
//     BLOCK_TAIL_CALL_OPTIMIZATION();
//     return result;
//   }
#if defined(__pnacl__)
#define BLOCK_TAIL_CALL_OPTIMIZATION() if (volatile int x = 0) { (void)x; }
#elif defined(__clang__)
// Clang will not tail call given inline volatile assembly.
#define BLOCK_TAIL_CALL_OPTIMIZATION() __asm__ __volatile__("")
#elif defined(__GNUC__)
// GCC will not tail call given inline volatile assembly.
#define BLOCK_TAIL_CALL_OPTIMIZATION() __asm__ __volatile__("")
#elif defined(_MSC_VER)
#include 
// The __nop() intrinsic blocks the optimisation.
#define ABSL_BLOCK_TAIL_CALL_OPTIMIZATION() __nop()
#else
#define ABSL_BLOCK_TAIL_CALL_OPTIMIZATION() \
  if (volatile int x = 0) {                 \
    (void)x;                                \
  }
#endif

Feb 4, 2024

[book] 你沒學到的資產配置 - 闕又上

人生五球

  • 工作
  • 家庭
  • 朋友
  • 健康
  • 心靈

工作是皮球 永遠有機會反彈 而其他四球為玻璃球。


投資標的

4 M; meaning, moat, management, margin of safety


投資準則

  1. 專業守則
    1. 事業是否簡單易懂
    2. 事業是否有一慣的營運紀錄
    3. 事業長期願景是否看好
  2. 管理團隊守則
    1. 理性
    2. 坦白對待股東(不是員工)
    3. 獨排眾議
  3. 財務守則
    1. ROE
    2. Owner earning
    3. 獲利率
    4. 保留一美元 能否創造一美元的市場價值
  4. 價值守則
    1. 公司價值為何
    2. 相當便宜的折扣買到它/投資它


Lucent(Bell Lab) 當年在父執輩是多麽頂尖拔萃的公司,如今安在?

70% 30%法則
公司債,國債比例。

長期債除非對一地區的未來有省慎的通盤理解,否則長期債不是好的投資標的。

Dec 31, 2023

[Cppcon 2023] Expressing Implementation Sameness and Similarity - Polymorphism in Modern C++, Daisy Hollman

Reference:
https://youtu.be/Fhw43xofyfo?si=PcMFEsqb7NRiCmyX

Two different kinds of sameness

Interface sameness

  • Enables users to treat things the same way in their code(create their own sameness)
  • Cannot be removed later
    • You can't change your user's code(at least not easily)
    • Once you allow users to treat things as the same, it's very hard to change that later
  • When done well: low code coupling(the degree of interdependence between software modules)

Implementation sameness

  • Enables readers to understand and use existing sameness of similarity
  • Can be changed or removed at any point in the future when it stops being helpful
  • When done well: high code cohesion(the degree to which the elements inside a module belong together)
Let this concept sinks in.

Consider about 'type of T'; e.g. template<typename T> vector{};


Reusing customization points.

Mixin mixins.

template<class> struct CRTPMixin;
template<template <class> class Mixin, class Derived>
struct CRTPMixin<Mixin<Derived>> {
  consteval auto& self() { return static_cast<Derived&>(*this); }
  consteval auto const& self() const { return static_cast<Derived const&>(*this); }
};

template<typename Derived>
struct PrintableElementwise : CRTPMixin<PrintableElementwise<Derived>> {
 void print() const {
    auto const& e = self().elements();
    std::apply([](auto const&... el) {
      ([&]{ cout << el << "\n"; }(), ...);
      }, e);
    }
};


As stated by Sy Brand's C++23’s Deducing this can help with the above

https://devblogs.microsoft.com/cppblog/cpp23-deducing-this/
static_cast<Derived const&>(*this); 
part. But really? Consider code uses deduce this from C++23:
struct PrintableElementwise {
  void print(this auto const& self) {
    auto const& e = self.elements();
    std::apply([](auto const&... el) {
      ([&]{ count << el << "\n"; }(), ...);
    }, e);
  }
};

struct Foo : PrintableElementwise {
 int a;
 double b;
 std::string s;
 auto elements() const {
    return std::forward_as_tuple(x, y, z);
 }
};
Above has mixed interface sameness with implementation sameness; which causes error:
auto items = std::vector<PrintableElementwise>{/*...*/};
for (auto* i : items) {
    i->print(); // error if derived type has no memfn elements().
}
Use the idea of 'type of T'. Which indicates the type's embedded behavior.


Qualifier forwarding

e.g.
Perfect forwarding:
template<class T>
void foo(T&& t) {
    bar(std::forward<T>(t));
}
equivalent to:
template<class T>
void foo(T& t) {
 bar(t);
}

template<class T>
using not_forwarding_ref = T;

template<class T>
void foo(not_forwarding_ref<T>&& t) {
  bar(std::move(t));
}


Don't Repeat Yourself(DRY)

'Every piece of knowledge must have a single, unambiguous, authoritative representation within a system


Separating the ownership mechanism (typical pattern for a class template customization point

From:

template<class Thing>
class OwingCollection {
 private:
   vector<unique_ptr<Thing>> things_;
 protected:
   void for_each(/* concept */ std::invocable<Thing const&> auto&& f) const { /*...*/};
 public:
   void insert(unique_ptr<Thing>) {};
   unique_ptr<Thing> remove(unique_ptr<Thing>) {};
   bool contains(unique_ptr<Thing>) const {};
   void remove_if(invocable<Thing const&> auto&&) {};
};
To:
template<class Thing, template<class...> class Owner = unique_ptr>
class OwingCollection {
 private:
   vector<Owner<Thing>> things_;
 protected:
   void for_each(/* concept */ std::invocable<Thing const&> auto&& f) const { /*...*/};
 public:
   void insert(Owner <Thing>) {};
   Owner <Thing> remove(Owner <Thing>) {};
   bool contains(Owner <Thing>) const {};
   void remove_if(invocable<Thing const&> auto&&) {};
};


STD's example of separable pattern 

[C++14] unique_ptr with type erasure as shared_ptr 


C++20 Concepts

C++20 concepts extract interface sameness without your permission.

Concepts allow library users to accidentally create code coupling between unrelated modules based only on names.
e.g.
template<class T>
  requires requires(T&& t) { { t.clear() } -> convertible_to<bool>; }
void do_the_stuff(T&& t) { /*...*/ }
Those two types fit for above API. 
However; their meaning of memfn clear() is different.
struct Container {
  // returns true if the container was
  // non-empty before the clear
  bool clear();
};

struct Color {
  // returns true if opacity == 0
  bool clear();
};
Concepts does not differentiate namespace.


More places having the concept of 'sameness'

  • 'Normal' functions (C like)
  • Macros and Code generation
    • 'Gross' but sometimes better than repeating things.
  • Customization Point Objects(CPOs)
  • Type erasure
  • constexpr functions
    • 'Sameness' of compile-time and runtime implementations.
  • Dependency injection (needs reflection)
  • Aspect-oriented programming(needs reflection)
  • Decoration(needs reflection)