Month: August 2011

After studying (50%?) of the most popular wpf features at a superficial level, I now feel at the “center” of the features are– data binding from VM to visuals– DProp

Many important features grow (extend, borrow) from the center– 2-way data binding– binding from visual to visual– data triggers– property triggers? based on DProp– AProp? based on DProp– command binding? borrows from data binding– Most controls rely on data binding– Most controls expose a lot of dependency properties, and these are easily programmable in mere xaml– a huge variety of requirements are now achievable in xaml without any c# code, largely due to the simple ideas in the “center”.

Any time you have a collection to show, ItemsControl and subtypes ListBox/ListView are the most popular choices. ItemsControl.Items is a property, whose type is ItemsCollection. By the way, ItemsCollection is a subtype of CollectionView — sorting, filter etc.

For Data binding, the target must be this.ItemsSource, not this.Items. Once using that, Items.Add() will trigger *runtime* exception. Instead, add to the data-bound physical collection instead. That collection is usually an ObservableCollection. After you add to it, the screen will auto-refresh, without any intervention.

Under the hood, I believe After the add/remove, the data binding engine queries the physical data and refreshes the display. Just put a breakpoint on the getter of the added item.

I talked to a few big and small low-latency shops. I feel latency optimization is “low-logic, high speed, high throughput”. Below are the Expertise required, but in any real system, you will see diminishing return on each aspect, so remember to prioritize the cost-effective areas to optimize. See my post on 80/20 (http://bigblog.tanbin.com/2012/03/8020-rule-dimishing-return.html)

Q: 3 threads are adding/remove/reading single elements in a hashmap. How do you optimize synchronization?
A (now i think): i guess lockfree is perhaps the best
A: concurrent hashmap with each segment holding multiple keys

Q: but if remover and reader use different keys, then why should they wait for each other?
A: they might hit the same bucket

I’d say it’s 90% different and 10% similar to a raw ptr. Smart pointers are class objects, way beyond 32-bit pointers. smart pointers overload de-referencer and many other operators to “look like” a raw pointer, but it’s really a class-template (Avoid the non-standard “template-class” jargon)

– pbclone? A raw pointer is always passed by clone (bitwise clone), just as in java. Smart pointers override copier (and op=), so a new instance is created based on the RHS smart pointer instance. Is this pbclone or pbref? I’d say more like pbclone.
– When you use a star to dereference a raw ptr, you simply dereference (unwrap) the real pointer. Smart pointer dereference is a high-level user-defined operation. There’s a get() method to return the real pointer, but I think we seldom need it.
– Similarly, you use an arrow to access a member of the pointee object, without the get() method.
– You can up/down cast raw pointers, not smart pointers.
– a raw ptr can be cast to void ptr. A smart ptr can’t.
– Raw pointers are key to virtual functions, not smart pointers.
– Creation and initialization is simple for raw pointers.
– size? A Smart pointer exceeds 32 bits except intrusive_ptr
– raw ptr has tight integration with arrays, with pointer arithmetic. Not smart ptr.
– double ptr sematics with 2 stars is natural for raw ptr, not smart ptr
– delete
– new? we can put raw ptr as lvalue of a “new” expression
– null assignment

In conclusion, raw pointers are such a part of the fabric. As a crude analogy, an e-book can feel like a paper book, but you can’t fold corners; can’t write anywhere using any pen; can’t spread 3 books out on your table; can’t tear off a page; can’t feel the thickness

I was asked to implement a generic LRU cache with size control. When size reaches a threshold, the LRU item must be kicked out. Optionally thread safe.

I came up with a concurrent hash map to provide fast get() and put(). Then I realized the kickout() operation would require a full scan of O(n) unless I provide an auxiliary data structure to physicallystore the nodes in lastAccess order. I came up with a sorted map (concurrent skip list map) of {time stamp –> key}. My idea was to __adjust__ the physical positions within the aux at every get() and put(). My “adjust” implementation basically removes an item from the aux and re-insert.

Alternatively, the key object could be decorated in a stampedKey objects with a mutable timestamp field and an immutable key field.

That was my back-of-envelope design. Let’s look at the standard solution — a LinkedHashMap with “A special constructor to create a linked hash map whose order of iteration is the order in which itsentries were last accessed, from least-recently accessed to most-recently (access-order). This kind of map is well-suited to building LRU caches. Invoking the put or get method results in an access to the corresponding entry (assuming it exists after the invocation completes). The putAll method generates one entry accessfor each mapping in the specified map, in the order that key-value mappings are provided by the specified map’s entry set iterator. No other methods generate entry accesses. In particular, operations on collection-views do not affect the order of iteration of the backing map.”

Apparently that too uses a regular hash table + an aux which is a linked list. (Linked list allows 2 nodes with identical time stamp. For my design to accommodate this, the stampedKey decorator might be storedin the aux.)

Without looking at its source code, I believe the adjustment uses remove-reinsert on the aux.

Q: removing (not kickout()) from linked list is O(n). How do you avoid that? Remember any remove() on the cache must hit both the hash table and the aux.%%A: the hash table entry holds a pointer to the node on the linked list

In WPF, the “event” word takes on multiple meanings. Know the subtle differences.

1) CLR event — used extensively in INPC. These events are generated by code, not user actions. Here “event” has the unique dotnet meaning. In other GUI systems (like swing), events are also generated from code, such as table change event after you add a row.

2) UI event from keyboard/mouse — the traditional GUI events, implemented (in WPF) with the CLR event + other things. These events have a hardware flavor.