- 
                Notifications
    
You must be signed in to change notification settings  - Fork 39
 
Open
Description
To reproduce, run AtomicArrayWithCAS2SingleWriterTest in test/day3/AtomicArrayTests.kt:
https://github.com/ndkoval/concurrent-programming-intensive
with the following implementation of AtomicArrayWithCAS2SingleWriter:
@file:Suppress("DuplicatedCode", "UNCHECKED_CAST")
package day3
import day3.AtomicArrayWithCAS2SingleWriter.Status.*
import java.util.concurrent.atomic.*
// This implementation never stores `null` values.
class AtomicArrayWithCAS2SingleWriter<E : Any>(size: Int, initialValue: E) {
    private val array = AtomicReferenceArray<Any?>(size)
    init {
        // Fill array with the initial value.
        for (i in 0 until size) {
            array[i] = initialValue
        }
    }
    fun get(index: Int): E {
        val curValue = array.get(index)
        if (curValue is AtomicArrayWithCAS2SingleWriter<*>.CAS2Descriptor) {
            val curStatus = curValue.status.get()
            if (curStatus == SUCCESS)
                return (if (curValue.index1 == index) curValue.update1 else curValue.update2) as E
            else
                return (if (curValue.index1 == index) curValue.expected1 else curValue.expected2) as E
        }
        return curValue as E
    }
    fun cas2(
        index1: Int, expected1: E, update1: E,
        index2: Int, expected2: E, update2: E
    ): Boolean {
        require(index1 != index2) { "The indices should be different" }
        val descriptor = CAS2Descriptor(
            index1 = index1, expected1 = expected1, update1 = update1,
            index2 = index2, expected2 = expected2, update2 = update2
        )
        descriptor.apply()
        return descriptor.status.get() === SUCCESS
    }
    inner class CAS2Descriptor(
        val index1: Int, val expected1: E, val update1: E,
        val index2: Int, val expected2: E, val update2: E
    ) {
        val status = AtomicReference(UNDECIDED)
        fun installDescriptor(): Boolean {
//            while(true) {
//                val curValue = array[index1]
//                if (curValue is AtomicArrayWithCAS2SingleWriter<*>.CAS2Descriptor) {
//                    curValue.apply()
//                    continue
//                }
                val desc1 = array.compareAndSet(index1, expected1, this)
                val desc2 = array.compareAndSet(index2, expected2, this)
                if (desc2 && desc1) {
                    return true
                } else {
                    if (desc2)
                        array.compareAndSet(index2, this, expected2)
                    if (desc1)
                        array.compareAndSet(index1, this, expected1)
                    return false;
                }
//            }
        }
        fun apply() {
            if (installDescriptor()) {
                status.compareAndSet(UNDECIDED, SUCCESS)
                array.compareAndSet(index1, this, update1)
                array.compareAndSet(index2, this, update2)
            }
            // TODO: Install the descriptor, update the status, and update the cells;
            // TODO: create functions for each of these three phases.
            // TODO: In this task, only one thread can call cas2(..),
            // TODO: so cas2(..) calls cannot be executed concurrently.
        }
    }
    enum class Status {
        UNDECIDED, SUCCESS, FAILED
    }
}Metadata
Metadata
Assignees
Labels
No labels